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