static void epochOffsetTest(int64_t epochOffset, int64_t units, UDateTimeScale scale) { UErrorCode status = U_ZERO_ERROR; int64_t universal = 0; int64_t universalEpoch = epochOffset * units; int64_t local = utmscale_toInt64(universalEpoch, scale, &status); if (local != 0) { log_err("utmscale_toInt64(epochOffset, scale, &status): scale = %d epochOffset = %lld, result = %lld.\n", scale, epochOffset, local); } local = utmscale_toInt64(0, scale, &status); if (local != -epochOffset) { log_err("utmscale_toInt64(0, scale): scale = %d, result = %lld.\n", scale, local); } universal = utmscale_fromInt64(-epochOffset, scale, &status); if (universal != 0) { log_err("from(-epochOffest, scale): scale = %d, epochOffset = %lld, result = %lld.\n", scale, epochOffset, universal); } universal = utmscale_fromInt64(0, scale, &status); if (universal != universalEpoch) { log_err("utmscale_fromInt64(0, scale): scale = %d, result = %lld.\n", scale, universal); } }
static void TestToInt64(void) { int32_t scale; int64_t result; UErrorCode status = U_ZERO_ERROR; result = utmscale_toInt64(0, -1, &status); if (status != U_ILLEGAL_ARGUMENT_ERROR) { log_err("utmscale_toInt64(0, -1, &status) did not generate U_ILLEGAL_ARGUMENT_ERROR.\n"); } for (scale = 0; scale < UDTS_MAX_SCALE; scale += 1) { int64_t toMin, toMax; status = U_ZERO_ERROR; toMin = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_TO_MIN_VALUE, &status); toMax = utmscale_getTimeScaleValue((UDateTimeScale)scale, UTSV_TO_MAX_VALUE, &status); status = U_ZERO_ERROR; result = utmscale_toInt64(0, (UDateTimeScale)scale, &status); if (status == U_ILLEGAL_ARGUMENT_ERROR) { log_err("utmscale_toInt64(0, %d, &status) generated U_ILLEGAL_ARGUMENT_ERROR.\n", scale); } status = U_ZERO_ERROR; result = utmscale_toInt64(toMin, (UDateTimeScale)scale, &status); if (status == U_ILLEGAL_ARGUMENT_ERROR) { log_err("utmscale_toInt64(toMin, %d, &status) generated U_ILLEGAL_ARGUMENT_ERROR.\n", scale); } if (toMin > U_INT64_MIN) { status = U_ZERO_ERROR; result = utmscale_toInt64(toMin - 1, (UDateTimeScale)scale, &status); if (status != U_ILLEGAL_ARGUMENT_ERROR) { log_err("utmscale_toInt64(toMin - 1, %d, &status) did not generate U_ILLEGAL_ARGUMENT_ERROR.\n", scale); } } status = U_ZERO_ERROR; result = utmscale_toInt64(toMax, (UDateTimeScale)scale, &status); if (status == U_ILLEGAL_ARGUMENT_ERROR) { log_err("utmscale_toInt64(toMax, %d, &status) generated U_ILLEGAL_ARGUMENT_ERROR.\n", scale); } if (toMax < U_INT64_MAX) { status = U_ZERO_ERROR; result = utmscale_toInt64(toMax + 1, (UDateTimeScale)scale, &status); if (status != U_ILLEGAL_ARGUMENT_ERROR) { log_err("utmscale_toInt64(toMax + 1, %d, &status) did not generate U_ILLEGAL_ARGUMENT_ERROR.\n", scale); } } } status = U_ZERO_ERROR; result = utmscale_toInt64(0, UDTS_MAX_SCALE, &status); if (status != U_ILLEGAL_ARGUMENT_ERROR) { log_err("utmscale_toInt64(0, UDTS_MAX_SCALE, &status) did not generate U_ILLEGAL_ARGUMENT_ERROR.\n"); } }
static void roundTripTest(int64_t value, UDateTimeScale scale) { UErrorCode status = U_ZERO_ERROR; int64_t rt = utmscale_toInt64(utmscale_fromInt64(value, scale, &status), scale, &status); if (rt != value) { log_err("Round-trip error: time scale = %d, value = %lld, round-trip = %lld.\n", scale, value, rt); } }
static void toLimitTest(int64_t toLimit, int64_t fromLimit, UDateTimeScale scale) { UErrorCode status = U_ZERO_ERROR; int64_t result = utmscale_toInt64(toLimit, scale, &status); if (result != fromLimit) { log_err("toLimit failure: scale = %d, toLimit = %lld , utmscale_toInt64(toLimit, scale, &status) = %lld, fromLimit = %lld.\n", scale, toLimit, result, fromLimit); } }
/* * ICU's Universal Time Scale is designed to be tick-for-tick compatible with * .Net System.DateTime. Verify that this is so for the * .Net-supported date range (years 1-9999 AD). * This requires a proleptic Gregorian calendar because that's what .Net uses. * Proleptic: No Julian/Gregorian switchover, or a switchover before * any date that we test, that is, before 0001 AD. */ static void TestDotNet() { static const UChar utc[] = { 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0 }; /* "Etc/GMT" */ const int32_t dayMillis = 86400 * INT64_C(1000); /* 1 day = 86400 seconds */ const int64_t dayTicks = 86400 * INT64_C(10000000); const DotNetDateTimeTicks *dt; UCalendar *cal; UErrorCode errorCode; UDate icuDate; int64_t ticks, millis; int32_t i; /* Open a proleptic Gregorian calendar. */ errorCode = U_ZERO_ERROR; cal = ucal_open(utc, -1, "", UCAL_GREGORIAN, &errorCode); ucal_setGregorianChange(cal, -1000000 * (dayMillis * (UDate)1), &errorCode); if(U_FAILURE(errorCode)) { log_err("ucal_open(UTC/proleptic Gregorian) failed: %s\n", u_errorName(errorCode)); ucal_close(cal); return; } for(i = 0; i < LENGTHOF(dotNetDateTimeTicks); ++i) { /* Test conversion from .Net/Universal time to ICU time. */ dt = dotNetDateTimeTicks + i; millis = utmscale_toInt64(dt->ticks, UDTS_ICU4C_TIME, &errorCode); ucal_clear(cal); ucal_setDate(cal, dt->year, dt->month - 1, dt->day, &errorCode); /* Java & ICU use January = month 0. */ icuDate = ucal_getMillis(cal, &errorCode); if(millis != icuDate) { /* Print days not millis to stay within printf() range. */ log_err("utmscale_toInt64(ticks[%d], ICU4C)=%dd != %dd=ucal_getMillis(%04d-%02d-%02d)\n", (int)i, (int)(millis/dayMillis), (int)(icuDate/dayMillis), (int)dt->year, (int)dt->month, (int)dt->day); } /* Test conversion from ICU time to .Net/Universal time. */ ticks = utmscale_fromInt64((int64_t)icuDate, UDTS_ICU4C_TIME, &errorCode); if(ticks != dt->ticks) { /* Print days not ticks to stay within printf() range. */ log_err("utmscale_fromInt64(date[%d], ICU4C)=%dd != %dd=.Net System.DateTime(%04d-%02d-%02d).Ticks\n", (int)i, (int)(ticks/dayTicks), (int)(dt->ticks/dayTicks), (int)dt->year, (int)dt->month, (int)dt->day); } } ucal_close(cal); }
void Win32DateTimeTest::testLocales(TestLog *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); if (found = uprv_getWindowsTimeZoneInfo(&tzi, equiv.getBuffer(), equiv.length())) { 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]; int32_t calType = 0; // NULL localeID means ICU didn't recognize this locale if (lcidRecords[i].localeID == NULL) { 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) calType, sizeof(int32_t)); 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(wdBuffer, wdLength - 1, 0) < 0) { UnicodeString baseName(wlocale.getBaseName()); UnicodeString expected(wdBuffer); log->errln("DateTime format error for locale " + baseName + ": expected date \"" + expected + "\" got \"" + ubBuffer + "\""); } if (ubBuffer.indexOf(wtBuffer, wtLength - 1, 0) < 0) { UnicodeString baseName(wlocale.getBaseName()); UnicodeString expected(wtBuffer); log->errln("DateTime format error for locale " + baseName + ": expected time \"" + expected + "\" got \"" + ubBuffer + "\""); } if (udBuffer.compare(wdBuffer) != 0) { UnicodeString baseName(wlocale.getBaseName()); UnicodeString expected(wdBuffer); log->errln("Date format error for locale " + baseName + ": expected \"" + expected + "\" got \"" + udBuffer + "\""); } if (utBuffer.compare(wtBuffer) != 0) { UnicodeString baseName(wlocale.getBaseName()); UnicodeString expected(wtBuffer); log->errln("Time format error for locale " + baseName + ": expected \"" + expected + "\" got \"" + utBuffer + "\""); } delete wbf; delete wdf; delete wtf; } Win32Utilities::freeLocales(lcidRecords); delete tz; }