1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 ********************************************************************************
5 * Copyright (C) 2005-2016, International Business Machines
6 * Corporation and others. All Rights Reserved.
7 ********************************************************************************
8 *
9 * File WINDTTST.CPP
10 *
11 ********************************************************************************
12 */
13
14 #include "unicode/utypes.h"
15
16 #if U_PLATFORM_HAS_WIN32_API
17
18 #if !UCONFIG_NO_FORMATTING
19
20 #include "unicode/format.h"
21 #include "unicode/numfmt.h"
22 #include "unicode/locid.h"
23 #include "unicode/ustring.h"
24 #include "unicode/testlog.h"
25 #include "unicode/utmscale.h"
26
27 #include "windtfmt.h"
28 #include "winutil.h"
29 #include "windttst.h"
30
31 #include "cmemory.h"
32 #include "cstring.h"
33 #include "locmap.h"
34 #include "wintzimpl.h"
35
36 # define WIN32_LEAN_AND_MEAN
37 # define VC_EXTRALEAN
38 # define NOUSER
39 # define NOSERVICE
40 # define NOIME
41 # define NOMCX
42 # include <windows.h>
43
getCalendarType(int32_t type)44 static const char *getCalendarType(int32_t type)
45 {
46 switch (type)
47 {
48 case 1:
49 case 2:
50 return "@calendar=gregorian";
51
52 case 3:
53 return "@calendar=japanese";
54
55 case 6:
56 return "@calendar=islamic";
57
58 case 7:
59 return "@calendar=buddhist";
60
61 case 8:
62 return "@calendar=hebrew";
63
64 default:
65 return "";
66 }
67 }
68
testLocales(TestLog * log)69 void Win32DateTimeTest::testLocales(TestLog *log)
70 {
71 SYSTEMTIME winNow;
72 UDate icuNow = 0;
73 SYSTEMTIME st;
74 FILETIME ft;
75 UnicodeString zoneID;
76 const TimeZone *tz = TimeZone::createDefault();
77 TIME_ZONE_INFORMATION tzi;
78
79 tz->getID(zoneID);
80 if (! uprv_getWindowsTimeZoneInfo(&tzi, zoneID.getBuffer(), zoneID.length())) {
81 UBool found = FALSE;
82 int32_t ec = TimeZone::countEquivalentIDs(zoneID);
83
84 for (int z = 0; z < ec; z += 1) {
85 UnicodeString equiv = TimeZone::getEquivalentID(zoneID, z);
86
87 if (found = uprv_getWindowsTimeZoneInfo(&tzi, equiv.getBuffer(), equiv.length())) {
88 break;
89 }
90 }
91
92 if (! found) {
93 GetTimeZoneInformation(&tzi);
94 }
95 }
96
97 GetSystemTime(&st);
98 SystemTimeToFileTime(&st, &ft);
99 SystemTimeToTzSpecificLocalTime(&tzi, &st, &winNow);
100
101 int64_t wftNow = ((int64_t) ft.dwHighDateTime << 32) + ft.dwLowDateTime;
102 UErrorCode status = U_ZERO_ERROR;
103
104 int64_t udtsNow = utmscale_fromInt64(wftNow, UDTS_WINDOWS_FILE_TIME, &status);
105
106 icuNow = (UDate) utmscale_toInt64(udtsNow, UDTS_ICU4C_TIME, &status);
107
108 int32_t lcidCount = 0;
109 Win32Utilities::LCIDRecord *lcidRecords = Win32Utilities::getLocales(lcidCount);
110
111 for(int i = 0; i < lcidCount; i += 1) {
112 UErrorCode status = U_ZERO_ERROR;
113 WCHAR longDateFormat[81], longTimeFormat[81], wdBuffer[256], wtBuffer[256];
114 int32_t calType = 0;
115
116 // NULL localeID means ICU didn't recognize this locale
117 if (lcidRecords[i].localeID == NULL) {
118 continue;
119 }
120
121 GetLocaleInfoW(lcidRecords[i].lcid, LOCALE_SLONGDATE, longDateFormat, 81);
122 GetLocaleInfoW(lcidRecords[i].lcid, LOCALE_STIMEFORMAT, longTimeFormat, 81);
123 GetLocaleInfoW(lcidRecords[i].lcid, LOCALE_RETURN_NUMBER|LOCALE_ICALENDARTYPE, (LPWSTR) calType, sizeof(int32_t));
124
125 char localeID[64];
126
127 uprv_strcpy(localeID, lcidRecords[i].localeID);
128 uprv_strcat(localeID, getCalendarType(calType));
129
130 UnicodeString ubBuffer, udBuffer, utBuffer;
131 Locale ulocale(localeID);
132 int32_t wdLength, wtLength;
133
134 wdLength = GetDateFormatW(lcidRecords[i].lcid, DATE_LONGDATE, &winNow, NULL, wdBuffer, UPRV_LENGTHOF(wdBuffer));
135 wtLength = GetTimeFormatW(lcidRecords[i].lcid, 0, &winNow, NULL, wtBuffer, UPRV_LENGTHOF(wtBuffer));
136
137 if (uprv_strchr(localeID, '@') > 0) {
138 uprv_strcat(localeID, ";");
139 } else {
140 uprv_strcat(localeID, "@");
141 }
142
143 uprv_strcat(localeID, "compat=host");
144
145 Locale wlocale(localeID);
146 DateFormat *wbf = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, wlocale);
147 DateFormat *wdf = DateFormat::createDateInstance(DateFormat::kFull, wlocale);
148 DateFormat *wtf = DateFormat::createTimeInstance(DateFormat::kFull, wlocale);
149
150 wbf->format(icuNow, ubBuffer);
151 wdf->format(icuNow, udBuffer);
152 wtf->format(icuNow, utBuffer);
153
154 if (ubBuffer.indexOf((const UChar *)wdBuffer, wdLength - 1, 0) < 0) {
155 UnicodeString baseName(wlocale.getBaseName());
156 UnicodeString expected((const UChar *)wdBuffer);
157
158 log->errln("DateTime format error for locale " + baseName + ": expected date \"" + expected +
159 "\" got \"" + ubBuffer + "\"");
160 }
161
162 if (ubBuffer.indexOf((const UChar *)wtBuffer, wtLength - 1, 0) < 0) {
163 UnicodeString baseName(wlocale.getBaseName());
164 UnicodeString expected((const UChar *)wtBuffer);
165
166 log->errln("DateTime format error for locale " + baseName + ": expected time \"" + expected +
167 "\" got \"" + ubBuffer + "\"");
168 }
169
170 if (udBuffer.compare((const UChar *)wdBuffer) != 0) {
171 UnicodeString baseName(wlocale.getBaseName());
172 UnicodeString expected((const UChar *)wdBuffer);
173
174 log->errln("Date format error for locale " + baseName + ": expected \"" + expected +
175 "\" got \"" + udBuffer + "\"");
176 }
177
178 if (utBuffer.compare((const UChar *)wtBuffer) != 0) {
179 UnicodeString baseName(wlocale.getBaseName());
180 UnicodeString expected((const UChar *)wtBuffer);
181
182 log->errln("Time format error for locale " + baseName + ": expected \"" + expected +
183 "\" got \"" + utBuffer + "\"");
184 }
185 delete wbf;
186 delete wdf;
187 delete wtf;
188 }
189
190 Win32Utilities::freeLocales(lcidRecords);
191 delete tz;
192 }
193
194 #endif /* #if !UCONFIG_NO_FORMATTING */
195
196 #endif /* U_PLATFORM_HAS_WIN32_API */
197