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
38U_NAMESPACE_USE
39
40static 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
120static 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 auxillary 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 */
151U_CAPI UBool U_EXPORT2
152uprv_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