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 48static 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 73void 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 if (found = uprv_getWindowsTimeZoneInfo(&tzi, equiv.getBuffer(), equiv.length())) { 92 break; 93 } 94 } 95 96 if (! found) { 97 GetTimeZoneInformation(&tzi); 98 } 99 } 100 101 GetSystemTime(&st); 102 SystemTimeToFileTime(&st, &ft); 103 SystemTimeToTzSpecificLocalTime(&tzi, &st, &winNow); 104 105 int64_t wftNow = ((int64_t) ft.dwHighDateTime << 32) + ft.dwLowDateTime; 106 UErrorCode status = U_ZERO_ERROR; 107 108 int64_t udtsNow = utmscale_fromInt64(wftNow, UDTS_WINDOWS_FILE_TIME, &status); 109 110 icuNow = (UDate) utmscale_toInt64(udtsNow, UDTS_ICU4C_TIME, &status); 111 112 int32_t lcidCount = 0; 113 Win32Utilities::LCIDRecord *lcidRecords = Win32Utilities::getLocales(lcidCount); 114 115 for(int i = 0; i < lcidCount; i += 1) { 116 UErrorCode status = U_ZERO_ERROR; 117 WCHAR longDateFormat[81], longTimeFormat[81], wdBuffer[256], wtBuffer[256]; 118 int32_t calType = 0; 119 120 // NULL localeID means ICU didn't recognize this locale 121 if (lcidRecords[i].localeID == NULL) { 122 continue; 123 } 124 125 // Some locales have had their names change over various OS releases; skip them in the test for now. 126 int32_t failingLocaleLCIDs[] = { 127 0x040a, /* es-ES_tradnl;es-ES-u-co-trad; */ 128 0x048c, /* fa-AF;prs-AF;prs-Arab-AF; */ 129 0x046b, /* qu-BO;quz-BO;quz-Latn-BO; */ 130 0x086b, /* qu-EC;quz-EC;quz-Latn-EC; */ 131 0x0c6b, /* qu-PE;quz-PE;quz-Latn-PE; */ 132 0x0492 /* ckb-IQ;ku-Arab-IQ; */ 133 }; 134 bool skip = (std::find(std::begin(failingLocaleLCIDs), std::end(failingLocaleLCIDs), lcidRecords[i].lcid) != std::end(failingLocaleLCIDs)); 135 if (skip && log->logKnownIssue("13119", "Windows '@compat=host' fails on down-level versions of the OS")) { 136 log->logln("ticket:13119 - Skipping LCID = 0x%04x", lcidRecords[i].lcid); 137 continue; 138 } 139 140 GetLocaleInfoW(lcidRecords[i].lcid, LOCALE_SLONGDATE, longDateFormat, 81); 141 GetLocaleInfoW(lcidRecords[i].lcid, LOCALE_STIMEFORMAT, longTimeFormat, 81); 142 GetLocaleInfoW(lcidRecords[i].lcid, LOCALE_RETURN_NUMBER|LOCALE_ICALENDARTYPE, (LPWSTR) calType, sizeof(int32_t)); 143 144 char localeID[64]; 145 146 uprv_strcpy(localeID, lcidRecords[i].localeID); 147 uprv_strcat(localeID, getCalendarType(calType)); 148 149 UnicodeString ubBuffer, udBuffer, utBuffer; 150 Locale ulocale(localeID); 151 int32_t wdLength, wtLength; 152 153 wdLength = GetDateFormatW(lcidRecords[i].lcid, DATE_LONGDATE, &winNow, NULL, wdBuffer, UPRV_LENGTHOF(wdBuffer)); 154 wtLength = GetTimeFormatW(lcidRecords[i].lcid, 0, &winNow, NULL, wtBuffer, UPRV_LENGTHOF(wtBuffer)); 155 156 if (uprv_strchr(localeID, '@') > 0) { 157 uprv_strcat(localeID, ";"); 158 } else { 159 uprv_strcat(localeID, "@"); 160 } 161 162 uprv_strcat(localeID, "compat=host"); 163 164 Locale wlocale(localeID); 165 DateFormat *wbf = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, wlocale); 166 DateFormat *wdf = DateFormat::createDateInstance(DateFormat::kFull, wlocale); 167 DateFormat *wtf = DateFormat::createTimeInstance(DateFormat::kFull, wlocale); 168 169 wbf->format(icuNow, ubBuffer); 170 wdf->format(icuNow, udBuffer); 171 wtf->format(icuNow, utBuffer); 172 173 if (ubBuffer.indexOf((const UChar *)wdBuffer, wdLength - 1, 0) < 0) { 174 UnicodeString baseName(wlocale.getBaseName()); 175 UnicodeString expected((const UChar *)wdBuffer); 176 177 log->errln("DateTime format error for locale " + baseName + ": expected date \"" + expected + 178 "\" got \"" + ubBuffer + "\""); 179 } 180 181 if (ubBuffer.indexOf((const UChar *)wtBuffer, wtLength - 1, 0) < 0) { 182 UnicodeString baseName(wlocale.getBaseName()); 183 UnicodeString expected((const UChar *)wtBuffer); 184 185 log->errln("DateTime format error for locale " + baseName + ": expected time \"" + expected + 186 "\" got \"" + ubBuffer + "\""); 187 } 188 189 if (udBuffer.compare((const UChar *)wdBuffer) != 0) { 190 UnicodeString baseName(wlocale.getBaseName()); 191 UnicodeString expected((const UChar *)wdBuffer); 192 193 log->errln("Date format error for locale " + baseName + ": expected \"" + expected + 194 "\" got \"" + udBuffer + "\""); 195 } 196 197 if (utBuffer.compare((const UChar *)wtBuffer) != 0) { 198 UnicodeString baseName(wlocale.getBaseName()); 199 UnicodeString expected((const UChar *)wtBuffer); 200 201 log->errln("Time format error for locale " + baseName + ": expected \"" + expected + 202 "\" got \"" + utBuffer + "\""); 203 } 204 delete wbf; 205 delete wdf; 206 delete wtf; 207 } 208 209 Win32Utilities::freeLocales(lcidRecords); 210 delete tz; 211} 212 213#endif /* #if !UCONFIG_NO_FORMATTING */ 214 215#endif /* U_PLATFORM_USES_ONLY_WIN32_API */ 216