• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 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_USES_ONLY_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 "dtfmttst.h"
32 
33 #include "cmemory.h"
34 #include "cstring.h"
35 #include "locmap.h"
36 #include "wintzimpl.h"
37 
38 #   define WIN32_LEAN_AND_MEAN
39 #   define VC_EXTRALEAN
40 #   define NOUSER
41 #   define NOSERVICE
42 #   define NOIME
43 #   define NOMCX
44 #   include <windows.h>
45 
46 #include <algorithm>
47 
getCalendarType(int32_t type)48 static const char *getCalendarType(int32_t type)
49 {
50     switch (type)
51     {
52     case 1:
53     case 2:
54         return "@calendar=gregorian";
55 
56     case 3:
57         return "@calendar=japanese";
58 
59     case 6:
60         return "@calendar=islamic";
61 
62     case 7:
63         return "@calendar=buddhist";
64 
65     case 8:
66         return "@calendar=hebrew";
67 
68     default:
69         return "";
70     }
71 }
72 
testLocales(DateFormatTest * log)73 void Win32DateTimeTest::testLocales(DateFormatTest *log)
74 {
75     SYSTEMTIME winNow;
76     UDate icuNow = 0;
77     SYSTEMTIME st;
78     FILETIME ft;
79     UnicodeString zoneID;
80     const TimeZone *tz = TimeZone::createDefault();
81     TIME_ZONE_INFORMATION tzi;
82 
83     tz->getID(zoneID);
84     if (! uprv_getWindowsTimeZoneInfo(&tzi, zoneID.getBuffer(), zoneID.length())) {
85         UBool found = FALSE;
86         int32_t ec = TimeZone::countEquivalentIDs(zoneID);
87 
88         for (int z = 0; z < ec; z += 1) {
89             UnicodeString equiv = TimeZone::getEquivalentID(zoneID, z);
90 
91             found = uprv_getWindowsTimeZoneInfo(&tzi, equiv.getBuffer(), equiv.length());
92             if (found) {
93                 break;
94             }
95         }
96 
97         if (! found) {
98             GetTimeZoneInformation(&tzi);
99         }
100     }
101 
102     GetSystemTime(&st);
103     SystemTimeToFileTime(&st, &ft);
104     SystemTimeToTzSpecificLocalTime(&tzi, &st, &winNow);
105 
106     int64_t wftNow = ((int64_t) ft.dwHighDateTime << 32) + ft.dwLowDateTime;
107     UErrorCode status = U_ZERO_ERROR;
108 
109     int64_t udtsNow = utmscale_fromInt64(wftNow, UDTS_WINDOWS_FILE_TIME, &status);
110 
111     icuNow = (UDate) utmscale_toInt64(udtsNow, UDTS_ICU4C_TIME, &status);
112 
113     int32_t lcidCount = 0;
114     Win32Utilities::LCIDRecord *lcidRecords = Win32Utilities::getLocales(lcidCount);
115 
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];
119         DWORD value = 0;
120         int32_t calType = 0;
121 
122         // NULL localeID means ICU didn't recognize this locale
123         if (lcidRecords[i].localeID == NULL) {
124             continue;
125         }
126 
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; */
135         };
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);
139             continue;
140         }
141 
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));
145 
146         calType = value;
147         char localeID[64];
148 
149         uprv_strcpy(localeID, lcidRecords[i].localeID);
150         uprv_strcat(localeID, getCalendarType(calType));
151 
152         UnicodeString ubBuffer, udBuffer, utBuffer;
153         Locale ulocale(localeID);
154         int32_t wdLength, wtLength;
155 
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));
158 
159         if (uprv_strchr(localeID, '@') > 0) {
160             uprv_strcat(localeID, ";");
161         } else {
162             uprv_strcat(localeID, "@");
163         }
164 
165         uprv_strcat(localeID, "compat=host");
166 
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);
171 
172         wbf->format(icuNow, ubBuffer);
173         wdf->format(icuNow, udBuffer);
174         wtf->format(icuNow, utBuffer);
175 
176         if (ubBuffer.indexOf((const UChar *)wdBuffer, wdLength - 1, 0) < 0) {
177             UnicodeString baseName(wlocale.getBaseName());
178             UnicodeString expected((const UChar *)wdBuffer);
179 
180             log->errln("DateTime format error for locale " + baseName + ": expected date \"" + expected +
181                        "\" got \"" + ubBuffer + "\"");
182         }
183 
184         if (ubBuffer.indexOf((const UChar *)wtBuffer, wtLength - 1, 0) < 0) {
185             UnicodeString baseName(wlocale.getBaseName());
186             UnicodeString expected((const UChar *)wtBuffer);
187 
188             log->errln("DateTime format error for locale " + baseName + ": expected time \"" + expected +
189                        "\" got \"" + ubBuffer + "\"");
190         }
191 
192         if (udBuffer.compare((const UChar *)wdBuffer) != 0) {
193             UnicodeString baseName(wlocale.getBaseName());
194             UnicodeString expected((const UChar *)wdBuffer);
195 
196             log->errln("Date format error for locale " + baseName + ": expected \"" + expected +
197                        "\" got \"" + udBuffer + "\"");
198         }
199 
200         if (utBuffer.compare((const UChar *)wtBuffer) != 0) {
201             UnicodeString baseName(wlocale.getBaseName());
202             UnicodeString expected((const UChar *)wtBuffer);
203 
204             log->errln("Time format error for locale " + baseName + ": expected \"" + expected +
205                        "\" got \"" + utBuffer + "\"");
206         }
207         delete wbf;
208         delete wdf;
209         delete wtf;
210     }
211 
212     Win32Utilities::freeLocales(lcidRecords);
213     delete tz;
214 }
215 
216 #endif /* #if !UCONFIG_NO_FORMATTING */
217 
218 #endif /* U_PLATFORM_USES_ONLY_WIN32_API */
219