1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 ********************************************************************************
5 * Copyright (C) 2005-2016, International Business Machines
6 * Corporation and others. All Rights Reserved.
7 ********************************************************************************
11 ********************************************************************************
14 #include "unicode/utypes.h"
16 #if U_PLATFORM_USES_ONLY_WIN32_API
18 #if !UCONFIG_NO_FORMATTING
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"
36 #include "wintzimpl.h"
38 # define WIN32_LEAN_AND_MEAN
48 static const char *getCalendarType(int32_t type
)
54 return "@calendar=gregorian";
57 return "@calendar=japanese";
60 return "@calendar=islamic";
63 return "@calendar=buddhist";
66 return "@calendar=hebrew";
73 void Win32DateTimeTest::testLocales(DateFormatTest
*log
)
80 const TimeZone
*tz
= TimeZone::createDefault();
81 TIME_ZONE_INFORMATION tzi
;
84 if (! uprv_getWindowsTimeZoneInfo(&tzi
, zoneID
.getBuffer(), zoneID
.length())) {
86 int32_t ec
= TimeZone::countEquivalentIDs(zoneID
);
88 for (int z
= 0; z
< ec
; z
+= 1) {
89 UnicodeString equiv
= TimeZone::getEquivalentID(zoneID
, z
);
91 found
= uprv_getWindowsTimeZoneInfo(&tzi
, equiv
.getBuffer(), equiv
.length());
98 GetTimeZoneInformation(&tzi
);
103 SystemTimeToFileTime(&st
, &ft
);
104 SystemTimeToTzSpecificLocalTime(&tzi
, &st
, &winNow
);
106 int64_t wftNow
= ((int64_t) ft
.dwHighDateTime
<< 32) + ft
.dwLowDateTime
;
107 UErrorCode status
= U_ZERO_ERROR
;
109 int64_t udtsNow
= utmscale_fromInt64(wftNow
, UDTS_WINDOWS_FILE_TIME
, &status
);
111 icuNow
= (UDate
) utmscale_toInt64(udtsNow
, UDTS_ICU4C_TIME
, &status
);
113 int32_t lcidCount
= 0;
114 Win32Utilities::LCIDRecord
*lcidRecords
= Win32Utilities::getLocales(lcidCount
);
116 for(int i
= 0; i
< lcidCount
; i
+= 1) {
117 UErrorCode status
= U_ZERO_ERROR
;
118 WCHAR longDateFormat
[81], longTimeFormat
[81], wdBuffer
[256], wtBuffer
[256];
122 // NULL localeID means ICU didn't recognize this locale
123 if (lcidRecords
[i
].localeID
== NULL
) {
127 // Some locales have had their names change over various OS releases; skip them in the test for now.
128 int32_t failingLocaleLCIDs
[] = {
129 0x040a, /* es-ES_tradnl;es-ES-u-co-trad; */
130 0x048c, /* fa-AF;prs-AF;prs-Arab-AF; */
131 0x046b, /* qu-BO;quz-BO;quz-Latn-BO; */
132 0x086b, /* qu-EC;quz-EC;quz-Latn-EC; */
133 0x0c6b, /* qu-PE;quz-PE;quz-Latn-PE; */
134 0x0492 /* ckb-IQ;ku-Arab-IQ; */
136 bool skip
= (std::find(std::begin(failingLocaleLCIDs
), std::end(failingLocaleLCIDs
), lcidRecords
[i
].lcid
) != std::end(failingLocaleLCIDs
));
137 if (skip
&& log
->logKnownIssue("13119", "Windows '@compat=host' fails on down-level versions of the OS")) {
138 log
->logln("ticket:13119 - Skipping LCID = 0x%04x", lcidRecords
[i
].lcid
);
142 GetLocaleInfoW(lcidRecords
[i
].lcid
, LOCALE_SLONGDATE
, longDateFormat
, 81);
143 GetLocaleInfoW(lcidRecords
[i
].lcid
, LOCALE_STIMEFORMAT
, longTimeFormat
, 81);
144 GetLocaleInfoW(lcidRecords
[i
].lcid
, LOCALE_RETURN_NUMBER
|LOCALE_ICALENDARTYPE
, (LPWSTR
)&value
, sizeof(value
)/sizeof(WCHAR
));
149 uprv_strcpy(localeID
, lcidRecords
[i
].localeID
);
150 uprv_strcat(localeID
, getCalendarType(calType
));
152 UnicodeString ubBuffer
, udBuffer
, utBuffer
;
153 Locale
ulocale(localeID
);
154 int32_t wdLength
, wtLength
;
156 wdLength
= GetDateFormatW(lcidRecords
[i
].lcid
, DATE_LONGDATE
, &winNow
, NULL
, wdBuffer
, UPRV_LENGTHOF(wdBuffer
));
157 wtLength
= GetTimeFormatW(lcidRecords
[i
].lcid
, 0, &winNow
, NULL
, wtBuffer
, UPRV_LENGTHOF(wtBuffer
));
159 if (uprv_strchr(localeID
, '@') > 0) {
160 uprv_strcat(localeID
, ";");
162 uprv_strcat(localeID
, "@");
165 uprv_strcat(localeID
, "compat=host");
167 Locale
wlocale(localeID
);
168 DateFormat
*wbf
= DateFormat::createDateTimeInstance(DateFormat::kFull
, DateFormat::kFull
, wlocale
);
169 DateFormat
*wdf
= DateFormat::createDateInstance(DateFormat::kFull
, wlocale
);
170 DateFormat
*wtf
= DateFormat::createTimeInstance(DateFormat::kFull
, wlocale
);
172 wbf
->format(icuNow
, ubBuffer
);
173 wdf
->format(icuNow
, udBuffer
);
174 wtf
->format(icuNow
, utBuffer
);
176 if (ubBuffer
.indexOf((const UChar
*)wdBuffer
, wdLength
- 1, 0) < 0) {
177 UnicodeString
baseName(wlocale
.getBaseName());
178 UnicodeString
expected((const UChar
*)wdBuffer
);
180 log
->errln("DateTime format error for locale " + baseName
+ ": expected date \"" + expected
+
181 "\" got \"" + ubBuffer
+ "\"");
184 if (ubBuffer
.indexOf((const UChar
*)wtBuffer
, wtLength
- 1, 0) < 0) {
185 UnicodeString
baseName(wlocale
.getBaseName());
186 UnicodeString
expected((const UChar
*)wtBuffer
);
188 log
->errln("DateTime format error for locale " + baseName
+ ": expected time \"" + expected
+
189 "\" got \"" + ubBuffer
+ "\"");
192 if (udBuffer
.compare((const UChar
*)wdBuffer
) != 0) {
193 UnicodeString
baseName(wlocale
.getBaseName());
194 UnicodeString
expected((const UChar
*)wdBuffer
);
196 log
->errln("Date format error for locale " + baseName
+ ": expected \"" + expected
+
197 "\" got \"" + udBuffer
+ "\"");
200 if (utBuffer
.compare((const UChar
*)wtBuffer
) != 0) {
201 UnicodeString
baseName(wlocale
.getBaseName());
202 UnicodeString
expected((const UChar
*)wtBuffer
);
204 log
->errln("Time format error for locale " + baseName
+ ": expected \"" + expected
+
205 "\" got \"" + utBuffer
+ "\"");
212 Win32Utilities::freeLocales(lcidRecords
);
216 #endif /* #if !UCONFIG_NO_FORMATTING */
218 #endif /* U_PLATFORM_USES_ONLY_WIN32_API */