1f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/*
2f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)********************************************************************************
3f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*   Copyright (C) 2009, International Business Machines
4f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*   Corporation and others.  All Rights Reserved.
5f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)********************************************************************************
6f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*
7f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* File WINTZIMPL.CPP
8f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*
9f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)********************************************************************************
10f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*/
11f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
12f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/utypes.h"
13f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
14f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#ifdef U_WINDOWS
15f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
16f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "wintzimpl.h"
17f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
18f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/unistr.h"
19f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/timezone.h"
20f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/basictz.h"
21f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "putilimp.h"
22f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "uassert.h"
23f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "cmemory.h"
24f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
25f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#   define WIN32_LEAN_AND_MEAN
26f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#   define VC_EXTRALEAN
27f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#   define NOUSER
28f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#   define NOSERVICE
29f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#   define NOIME
30f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#   define NOMCX
31f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
32f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include <windows.h>
33f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
34f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_NAMESPACE_USE
35f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
36f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static UBool getSystemTimeInformation(TimeZone *tz, SYSTEMTIME &daylightDate, SYSTEMTIME &standardDate, int32_t &bias, int32_t &daylightBias, int32_t &standardBias) {
37f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UErrorCode status = U_ZERO_ERROR;
38f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UBool result = TRUE;
39f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    BasicTimeZone *btz = (BasicTimeZone*)tz; // we should check type
40f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    InitialTimeZoneRule *initial = NULL;
41f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    AnnualTimeZoneRule *std = NULL, *dst = NULL;
42f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
43f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    btz->getSimpleRulesNear(uprv_getUTCtime(), initial, std, dst, status);
44f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_SUCCESS(status)) {
45f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (std == NULL || dst == NULL) {
46f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            bias = -1 * (initial->getRawOffset()/60000);
47f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            standardBias = 0;
48f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            daylightBias = 0;
49f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // Do not use DST.  Set 0 to all stadardDate/daylightDate fields
50f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            standardDate.wYear = standardDate.wMonth  = standardDate.wDayOfWeek = standardDate.wDay =
51f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            standardDate.wHour = standardDate.wMinute = standardDate.wSecond    = standardDate.wMilliseconds = 0;
52f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            daylightDate.wYear = daylightDate.wMonth  = daylightDate.wDayOfWeek = daylightDate.wDay =
53f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            daylightDate.wHour = daylightDate.wMinute = daylightDate.wSecond    = daylightDate.wMilliseconds = 0;
54f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        } else {
55f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            U_ASSERT(std->getRule()->getDateRuleType() == DateTimeRule::DOW);
56f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            U_ASSERT(dst->getRule()->getDateRuleType() == DateTimeRule::DOW);
57f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
58f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            bias = -1 * (std->getRawOffset()/60000);
59f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            standardBias = 0;
60f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            daylightBias = -1 * (dst->getDSTSavings()/60000);
61f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            // Always use DOW type rule
62f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            int32_t hour, min, sec, mil;
63f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            standardDate.wYear = 0;
64f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            standardDate.wMonth = std->getRule()->getRuleMonth() + 1;
65f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            standardDate.wDay = std->getRule()->getRuleWeekInMonth();
66f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (standardDate.wDay < 0) {
67f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                standardDate.wDay = 5;
68f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
69f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            standardDate.wDayOfWeek = std->getRule()->getRuleDayOfWeek() - 1;
70f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
71f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            mil = std->getRule()->getRuleMillisInDay();
72f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            hour = mil/3600000;
73f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            mil %= 3600000;
74f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            min = mil/60000;
75f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            mil %= 60000;
76f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            sec = mil/1000;
77f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            mil %= 1000;
78f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
79f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            standardDate.wHour = hour;
80f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            standardDate.wMinute = min;
81f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            standardDate.wSecond = sec;
82f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            standardDate.wMilliseconds = mil;
83f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
84f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            daylightDate.wYear = 0;
85f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            daylightDate.wMonth = dst->getRule()->getRuleMonth() + 1;
86f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            daylightDate.wDay = dst->getRule()->getRuleWeekInMonth();
87f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (daylightDate.wDay < 0) {
88f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                daylightDate.wDay = 5;
89f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
90f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            daylightDate.wDayOfWeek = dst->getRule()->getRuleDayOfWeek() - 1;
91f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
92f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            mil = dst->getRule()->getRuleMillisInDay();
93f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            hour = mil/3600000;
94f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            mil %= 3600000;
95f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            min = mil/60000;
96f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            mil %= 60000;
97f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            sec = mil/1000;
98f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            mil %= 1000;
99f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
100f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            daylightDate.wHour = hour;
101f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            daylightDate.wMinute = min;
102f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            daylightDate.wSecond = sec;
103f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            daylightDate.wMilliseconds = mil;
104f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
105f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
106f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        result = FALSE;
107f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
108f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
109f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    delete initial;
110f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    delete std;
111f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    delete dst;
112f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
113f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return result;
114f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
115f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
116f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static UBool getWindowsTimeZoneInfo(TIME_ZONE_INFORMATION *zoneInfo, const UChar *icuid, int32_t length) {
117f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UBool result = FALSE;
118f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UnicodeString id = UnicodeString(icuid, length);
119f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    TimeZone *tz = TimeZone::createTimeZone(id);
120f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
121f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (tz != NULL) {
122f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        int32_t bias;
123f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        int32_t daylightBias;
124f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        int32_t standardBias;
125f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        SYSTEMTIME daylightDate;
126f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        SYSTEMTIME standardDate;
127f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
128f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (getSystemTimeInformation(tz, daylightDate, standardDate, bias, daylightBias, standardBias)) {
129f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            uprv_memset(zoneInfo, 0, sizeof(TIME_ZONE_INFORMATION)); // We do not set standard/daylight names, so nullify first.
130f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            zoneInfo->Bias          = bias;
131f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            zoneInfo->DaylightBias  = daylightBias;
132f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            zoneInfo->StandardBias  = standardBias;
133f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            zoneInfo->DaylightDate  = daylightDate;
134f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            zoneInfo->StandardDate  = standardDate;
135f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
136f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            result = TRUE;
137f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
138f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
139f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
140f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return result;
141f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
142f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
143f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/*
144f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Given the timezone icuid, fill in zoneInfo by calling auxillary functions that creates a timezone and extract the
145f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * information to put into zoneInfo. This includes bias and standard time date and daylight saving date.
146f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */
147f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI UBool U_EXPORT2
148f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)uprv_getWindowsTimeZoneInfo(TIME_ZONE_INFORMATION *zoneInfo, const UChar *icuid, int32_t length)
149f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
150f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (getWindowsTimeZoneInfo(zoneInfo, icuid, length)) {
151f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return TRUE;
152f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
153f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return FALSE;
154f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
155f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
156f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
157f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#endif
158