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
44static 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
69void 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