| // © 2016 and later: Unicode, Inc. and others. |
| // License & terms of use: http://www.unicode.org/copyright.html |
| /* |
| ******************************************************************************** |
| * Copyright (C) 2005-2016, International Business Machines |
| * Corporation and others. All Rights Reserved. |
| ******************************************************************************** |
| * |
| * File WINDTTST.CPP |
| * |
| ******************************************************************************** |
| */ |
| |
| #include "unicode/utypes.h" |
| |
| #if U_PLATFORM_USES_ONLY_WIN32_API |
| |
| #if !UCONFIG_NO_FORMATTING |
| |
| #include "unicode/format.h" |
| #include "unicode/numfmt.h" |
| #include "unicode/locid.h" |
| #include "unicode/ustring.h" |
| #include "unicode/testlog.h" |
| #include "unicode/utmscale.h" |
| |
| #include "windtfmt.h" |
| #include "winutil.h" |
| #include "windttst.h" |
| |
| #include "dtfmttst.h" |
| |
| #include "cmemory.h" |
| #include "cstring.h" |
| #include "locmap.h" |
| #include "wintzimpl.h" |
| |
| # define WIN32_LEAN_AND_MEAN |
| # define VC_EXTRALEAN |
| # define NOUSER |
| # define NOSERVICE |
| # define NOIME |
| # define NOMCX |
| # include <windows.h> |
| |
| #include <algorithm> |
| |
| static const char *getCalendarType(int32_t type) |
| { |
| switch (type) |
| { |
| case 1: |
| case 2: |
| return "@calendar=gregorian"; |
| |
| case 3: |
| return "@calendar=japanese"; |
| |
| case 6: |
| return "@calendar=islamic"; |
| |
| case 7: |
| return "@calendar=buddhist"; |
| |
| case 8: |
| return "@calendar=hebrew"; |
| |
| default: |
| return ""; |
| } |
| } |
| |
| void Win32DateTimeTest::testLocales(DateFormatTest *log) |
| { |
| SYSTEMTIME winNow; |
| UDate icuNow = 0; |
| SYSTEMTIME st; |
| FILETIME ft; |
| UnicodeString zoneID; |
| const TimeZone *tz = TimeZone::createDefault(); |
| TIME_ZONE_INFORMATION tzi; |
| |
| tz->getID(zoneID); |
| if (! uprv_getWindowsTimeZoneInfo(&tzi, zoneID.getBuffer(), zoneID.length())) { |
| UBool found = FALSE; |
| int32_t ec = TimeZone::countEquivalentIDs(zoneID); |
| |
| for (int z = 0; z < ec; z += 1) { |
| UnicodeString equiv = TimeZone::getEquivalentID(zoneID, z); |
| |
| found = uprv_getWindowsTimeZoneInfo(&tzi, equiv.getBuffer(), equiv.length()); |
| if (found) { |
| break; |
| } |
| } |
| |
| if (! found) { |
| GetTimeZoneInformation(&tzi); |
| } |
| } |
| |
| GetSystemTime(&st); |
| SystemTimeToFileTime(&st, &ft); |
| SystemTimeToTzSpecificLocalTime(&tzi, &st, &winNow); |
| |
| int64_t wftNow = ((int64_t) ft.dwHighDateTime << 32) + ft.dwLowDateTime; |
| UErrorCode status = U_ZERO_ERROR; |
| |
| int64_t udtsNow = utmscale_fromInt64(wftNow, UDTS_WINDOWS_FILE_TIME, &status); |
| |
| icuNow = (UDate) utmscale_toInt64(udtsNow, UDTS_ICU4C_TIME, &status); |
| |
| int32_t lcidCount = 0; |
| Win32Utilities::LCIDRecord *lcidRecords = Win32Utilities::getLocales(lcidCount); |
| |
| for(int i = 0; i < lcidCount; i += 1) { |
| UErrorCode status = U_ZERO_ERROR; |
| WCHAR longDateFormat[81], longTimeFormat[81], wdBuffer[256], wtBuffer[256]; |
| DWORD value = 0; |
| int32_t calType = 0; |
| |
| // NULL localeID means ICU didn't recognize this locale |
| if (lcidRecords[i].localeID == NULL) { |
| continue; |
| } |
| |
| // Some locales have had their names change over various OS releases; skip them in the test for now. |
| int32_t failingLocaleLCIDs[] = { |
| 0x040a, /* es-ES_tradnl;es-ES-u-co-trad; */ |
| 0x048c, /* fa-AF;prs-AF;prs-Arab-AF; */ |
| 0x046b, /* qu-BO;quz-BO;quz-Latn-BO; */ |
| 0x086b, /* qu-EC;quz-EC;quz-Latn-EC; */ |
| 0x0c6b, /* qu-PE;quz-PE;quz-Latn-PE; */ |
| 0x0492 /* ckb-IQ;ku-Arab-IQ; */ |
| }; |
| bool skip = (std::find(std::begin(failingLocaleLCIDs), std::end(failingLocaleLCIDs), lcidRecords[i].lcid) != std::end(failingLocaleLCIDs)); |
| if (skip && log->logKnownIssue("13119", "Windows '@compat=host' fails on down-level versions of the OS")) { |
| log->logln("ticket:13119 - Skipping LCID = 0x%04x", lcidRecords[i].lcid); |
| continue; |
| } |
| |
| GetLocaleInfoW(lcidRecords[i].lcid, LOCALE_SLONGDATE, longDateFormat, 81); |
| GetLocaleInfoW(lcidRecords[i].lcid, LOCALE_STIMEFORMAT, longTimeFormat, 81); |
| GetLocaleInfoW(lcidRecords[i].lcid, LOCALE_RETURN_NUMBER|LOCALE_ICALENDARTYPE, (LPWSTR)&value, sizeof(value)/sizeof(WCHAR)); |
| |
| calType = value; |
| char localeID[64]; |
| |
| uprv_strcpy(localeID, lcidRecords[i].localeID); |
| uprv_strcat(localeID, getCalendarType(calType)); |
| |
| UnicodeString ubBuffer, udBuffer, utBuffer; |
| Locale ulocale(localeID); |
| int32_t wdLength, wtLength; |
| |
| wdLength = GetDateFormatW(lcidRecords[i].lcid, DATE_LONGDATE, &winNow, NULL, wdBuffer, UPRV_LENGTHOF(wdBuffer)); |
| wtLength = GetTimeFormatW(lcidRecords[i].lcid, 0, &winNow, NULL, wtBuffer, UPRV_LENGTHOF(wtBuffer)); |
| |
| if (uprv_strchr(localeID, '@') > 0) { |
| uprv_strcat(localeID, ";"); |
| } else { |
| uprv_strcat(localeID, "@"); |
| } |
| |
| uprv_strcat(localeID, "compat=host"); |
| |
| Locale wlocale(localeID); |
| DateFormat *wbf = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, wlocale); |
| DateFormat *wdf = DateFormat::createDateInstance(DateFormat::kFull, wlocale); |
| DateFormat *wtf = DateFormat::createTimeInstance(DateFormat::kFull, wlocale); |
| |
| wbf->format(icuNow, ubBuffer); |
| wdf->format(icuNow, udBuffer); |
| wtf->format(icuNow, utBuffer); |
| |
| if (ubBuffer.indexOf((const UChar *)wdBuffer, wdLength - 1, 0) < 0) { |
| UnicodeString baseName(wlocale.getBaseName()); |
| UnicodeString expected((const UChar *)wdBuffer); |
| |
| log->errln("DateTime format error for locale " + baseName + ": expected date \"" + expected + |
| "\" got \"" + ubBuffer + "\""); |
| } |
| |
| if (ubBuffer.indexOf((const UChar *)wtBuffer, wtLength - 1, 0) < 0) { |
| UnicodeString baseName(wlocale.getBaseName()); |
| UnicodeString expected((const UChar *)wtBuffer); |
| |
| log->errln("DateTime format error for locale " + baseName + ": expected time \"" + expected + |
| "\" got \"" + ubBuffer + "\""); |
| } |
| |
| if (udBuffer.compare((const UChar *)wdBuffer) != 0) { |
| UnicodeString baseName(wlocale.getBaseName()); |
| UnicodeString expected((const UChar *)wdBuffer); |
| |
| log->errln("Date format error for locale " + baseName + ": expected \"" + expected + |
| "\" got \"" + udBuffer + "\""); |
| } |
| |
| if (utBuffer.compare((const UChar *)wtBuffer) != 0) { |
| UnicodeString baseName(wlocale.getBaseName()); |
| UnicodeString expected((const UChar *)wtBuffer); |
| |
| log->errln("Time format error for locale " + baseName + ": expected \"" + expected + |
| "\" got \"" + utBuffer + "\""); |
| } |
| delete wbf; |
| delete wdf; |
| delete wtf; |
| } |
| |
| Win32Utilities::freeLocales(lcidRecords); |
| delete tz; |
| } |
| |
| #endif /* #if !UCONFIG_NO_FORMATTING */ |
| |
| #endif /* U_PLATFORM_USES_ONLY_WIN32_API */ |