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