OLD | NEW |
(Empty) | |
| 1 /*********************************************************************** |
| 2 * COPYRIGHT: |
| 3 * Copyright (c) 1997-2010, International Business Machines Corporation |
| 4 * and others. All Rights Reserved. |
| 5 ***********************************************************************/ |
| 6 |
| 7 #include "unicode/utypes.h" |
| 8 |
| 9 #if !UCONFIG_NO_FORMATTING |
| 10 |
| 11 #include "unicode/timezone.h" |
| 12 #include "unicode/simpletz.h" |
| 13 #include "unicode/calendar.h" |
| 14 #include "unicode/gregocal.h" |
| 15 #include "unicode/resbund.h" |
| 16 #include "unicode/strenum.h" |
| 17 #include "tztest.h" |
| 18 #include "cmemory.h" |
| 19 #include "putilimp.h" |
| 20 #include "cstring.h" |
| 21 #include "olsontz.h" |
| 22 |
| 23 #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) |
| 24 |
| 25 #define CASE(id,test) case id: \ |
| 26 name = #test; \ |
| 27 if (exec) { \ |
| 28 logln(#test "---"); logln(""); \ |
| 29 test(); \ |
| 30 } \ |
| 31 break |
| 32 |
| 33 // ***************************************************************************** |
| 34 // class TimeZoneTest |
| 35 // ***************************************************************************** |
| 36 |
| 37 // TODO: We should probably read following data at runtime, so we can update |
| 38 // these values every release with necessary data changes. |
| 39 const int32_t TimeZoneTest::REFERENCE_YEAR = 2009; |
| 40 const char * TimeZoneTest::REFERENCE_DATA_VERSION = "2009d"; |
| 41 |
| 42 void TimeZoneTest::runIndexedTest( int32_t index, UBool exec, const char* &name,
char* /*par*/ ) |
| 43 { |
| 44 if (exec) logln("TestSuite TestTimeZone"); |
| 45 switch (index) { |
| 46 CASE(0, TestPRTOffset); |
| 47 CASE(1, TestVariousAPI518); |
| 48 CASE(2, TestGetAvailableIDs913); |
| 49 CASE(3, TestGenericAPI); |
| 50 CASE(4, TestRuleAPI); |
| 51 CASE(5, TestShortZoneIDs); |
| 52 CASE(6, TestCustomParse); |
| 53 CASE(7, TestDisplayName); |
| 54 CASE(8, TestDSTSavings); |
| 55 CASE(9, TestAlternateRules); |
| 56 CASE(10,TestCountries); |
| 57 CASE(11,TestHistorical); |
| 58 CASE(12,TestEquivalentIDs); |
| 59 CASE(13, TestAliasedNames); |
| 60 CASE(14, TestFractionalDST); |
| 61 CASE(15, TestFebruary); |
| 62 CASE(16, TestCanonicalID); |
| 63 CASE(17, TestDisplayNamesMeta); |
| 64 default: name = ""; break; |
| 65 } |
| 66 } |
| 67 |
| 68 const int32_t TimeZoneTest::millisPerHour = 3600000; |
| 69 |
| 70 // -----------------------------------------------------------------------------
---- |
| 71 |
| 72 /** |
| 73 * Generic API testing for API coverage. |
| 74 */ |
| 75 void |
| 76 TimeZoneTest::TestGenericAPI() |
| 77 { |
| 78 UnicodeString id("NewGMT"); |
| 79 int32_t offset = 12345; |
| 80 |
| 81 SimpleTimeZone *zone = new SimpleTimeZone(offset, id); |
| 82 if (zone->useDaylightTime()) errln("FAIL: useDaylightTime should return FALS
E"); |
| 83 |
| 84 TimeZone* zoneclone = zone->clone(); |
| 85 if (!(*zoneclone == *zone)) errln("FAIL: clone or operator== failed"); |
| 86 zoneclone->setID("abc"); |
| 87 if (!(*zoneclone != *zone)) errln("FAIL: clone or operator!= failed"); |
| 88 delete zoneclone; |
| 89 |
| 90 zoneclone = zone->clone(); |
| 91 if (!(*zoneclone == *zone)) errln("FAIL: clone or operator== failed"); |
| 92 zoneclone->setRawOffset(45678); |
| 93 if (!(*zoneclone != *zone)) errln("FAIL: clone or operator!= failed"); |
| 94 |
| 95 SimpleTimeZone copy(*zone); |
| 96 if (!(copy == *zone)) errln("FAIL: copy constructor or operator== failed"); |
| 97 copy = *(SimpleTimeZone*)zoneclone; |
| 98 if (!(copy == *zoneclone)) errln("FAIL: assignment operator or operator== fa
iled"); |
| 99 |
| 100 TimeZone* saveDefault = TimeZone::createDefault(); |
| 101 logln((UnicodeString)"TimeZone::createDefault() => " + saveDefault->getID(id
)); |
| 102 TimeZone* pstZone = TimeZone::createTimeZone("America/Los_Angeles"); |
| 103 |
| 104 logln("call uprv_timezone() which uses the host"); |
| 105 logln("to get the difference in seconds between coordinated universal"); |
| 106 logln("time and local time. E.g., -28,800 for PST (GMT-8hrs)"); |
| 107 |
| 108 int32_t tzoffset = uprv_timezone(); |
| 109 logln(UnicodeString("Value returned from uprv_timezone = ") + tzoffset); |
| 110 // Invert sign because UNIX semantics are backwards |
| 111 if (tzoffset < 0) |
| 112 tzoffset = -tzoffset; |
| 113 if ((*saveDefault == *pstZone) && (tzoffset != 28800)) { |
| 114 errln("FAIL: t_timezone may be incorrect. It is not 28800"); |
| 115 } |
| 116 |
| 117 if ((tzoffset % 900) != 0) { |
| 118 /* |
| 119 * Ticket#6364 and #7648 |
| 120 * A few time zones are using GMT offests not a multiple of 15 minutes. |
| 121 * Therefore, we should not interpret such case as an error. |
| 122 * We downgrade this from errln to infoln. When we see this message, |
| 123 * we should examine if it is ignorable or not. |
| 124 */ |
| 125 infoln("WARNING: t_timezone may be incorrect. It is not a multiple of 15
min.", tzoffset); |
| 126 } |
| 127 |
| 128 TimeZone::adoptDefault(zone); |
| 129 TimeZone* defaultzone = TimeZone::createDefault(); |
| 130 if (defaultzone == zone || |
| 131 !(*defaultzone == *zone)) |
| 132 errln("FAIL: createDefault failed"); |
| 133 TimeZone::adoptDefault(saveDefault); |
| 134 delete defaultzone; |
| 135 delete zoneclone; |
| 136 delete pstZone; |
| 137 |
| 138 UErrorCode status = U_ZERO_ERROR; |
| 139 const char* tzver = TimeZone::getTZDataVersion(status); |
| 140 if (U_FAILURE(status)) { |
| 141 errcheckln(status, "FAIL: getTZDataVersion failed - %s", u_errorName(sta
tus)); |
| 142 } else if (uprv_strlen(tzver) != 5 /* 4 digits + 1 letter */) { |
| 143 errln((UnicodeString)"FAIL: getTZDataVersion returned " + tzver); |
| 144 } else { |
| 145 logln((UnicodeString)"tzdata version: " + tzver); |
| 146 } |
| 147 } |
| 148 |
| 149 // -----------------------------------------------------------------------------
---- |
| 150 |
| 151 /** |
| 152 * Test the setStartRule/setEndRule API calls. |
| 153 */ |
| 154 void |
| 155 TimeZoneTest::TestRuleAPI() |
| 156 { |
| 157 UErrorCode status = U_ZERO_ERROR; |
| 158 |
| 159 UDate offset = 60*60*1000*1.75; // Pick a weird offset |
| 160 SimpleTimeZone *zone = new SimpleTimeZone((int32_t)offset, "TestZone"); |
| 161 if (zone->useDaylightTime()) errln("FAIL: useDaylightTime should return FALS
E"); |
| 162 |
| 163 // Establish our expected transition times. Do this with a non-DST |
| 164 // calendar with the (above) declared local offset. |
| 165 GregorianCalendar *gc = new GregorianCalendar(*zone, status); |
| 166 if (failure(status, "new GregorianCalendar", TRUE)) return; |
| 167 gc->clear(); |
| 168 gc->set(1990, UCAL_MARCH, 1); |
| 169 UDate marchOneStd = gc->getTime(status); // Local Std time midnight |
| 170 gc->clear(); |
| 171 gc->set(1990, UCAL_JULY, 1); |
| 172 UDate julyOneStd = gc->getTime(status); // Local Std time midnight |
| 173 if (failure(status, "GregorianCalendar::getTime")) return; |
| 174 |
| 175 // Starting and ending hours, WALL TIME |
| 176 int32_t startHour = (int32_t)(2.25 * 3600000); |
| 177 int32_t endHour = (int32_t)(3.5 * 3600000); |
| 178 |
| 179 zone->setStartRule(UCAL_MARCH, 1, 0, startHour, status); |
| 180 zone->setEndRule (UCAL_JULY, 1, 0, endHour, status); |
| 181 |
| 182 delete gc; |
| 183 gc = new GregorianCalendar(*zone, status); |
| 184 if (failure(status, "new GregorianCalendar")) return; |
| 185 |
| 186 UDate marchOne = marchOneStd + startHour; |
| 187 UDate julyOne = julyOneStd + endHour - 3600000; // Adjust from wall to Std t
ime |
| 188 |
| 189 UDate expMarchOne = 636251400000.0; |
| 190 if (marchOne != expMarchOne) |
| 191 { |
| 192 errln((UnicodeString)"FAIL: Expected start computed as " + marchOne + |
| 193 " = " + dateToString(marchOne)); |
| 194 logln((UnicodeString)" Should be " + expMarchOne + |
| 195 " = " + dateToString(expMarchOne)); |
| 196 } |
| 197 |
| 198 UDate expJulyOne = 646793100000.0; |
| 199 if (julyOne != expJulyOne) |
| 200 { |
| 201 errln((UnicodeString)"FAIL: Expected start computed as " + julyOne + |
| 202 " = " + dateToString(julyOne)); |
| 203 logln((UnicodeString)" Should be " + expJulyOne + |
| 204 " = " + dateToString(expJulyOne)); |
| 205 } |
| 206 |
| 207 testUsingBinarySearch(*zone, date(90, UCAL_JANUARY, 1), date(90, UCAL_JUNE,
15), marchOne); |
| 208 testUsingBinarySearch(*zone, date(90, UCAL_JUNE, 1), date(90, UCAL_DECEMBER,
31), julyOne); |
| 209 |
| 210 if (zone->inDaylightTime(marchOne - 1000, status) || |
| 211 !zone->inDaylightTime(marchOne, status)) |
| 212 errln("FAIL: Start rule broken"); |
| 213 if (!zone->inDaylightTime(julyOne - 1000, status) || |
| 214 zone->inDaylightTime(julyOne, status)) |
| 215 errln("FAIL: End rule broken"); |
| 216 |
| 217 zone->setStartYear(1991); |
| 218 if (zone->inDaylightTime(marchOne, status) || |
| 219 zone->inDaylightTime(julyOne - 1000, status)) |
| 220 errln("FAIL: Start year broken"); |
| 221 |
| 222 failure(status, "TestRuleAPI"); |
| 223 delete gc; |
| 224 delete zone; |
| 225 } |
| 226 |
| 227 void |
| 228 TimeZoneTest::findTransition(const TimeZone& tz, |
| 229 UDate min, UDate max) { |
| 230 UErrorCode ec = U_ZERO_ERROR; |
| 231 UnicodeString id,s; |
| 232 UBool startsInDST = tz.inDaylightTime(min, ec); |
| 233 if (failure(ec, "TimeZone::inDaylightTime")) return; |
| 234 if (tz.inDaylightTime(max, ec) == startsInDST) { |
| 235 logln("Error: " + tz.getID(id) + ".inDaylightTime(" + dateToString(min)
+ ") = " + (startsInDST?"TRUE":"FALSE") + |
| 236 ", inDaylightTime(" + dateToString(max) + ") = " + (startsInDST?"T
RUE":"FALSE")); |
| 237 return; |
| 238 } |
| 239 if (failure(ec, "TimeZone::inDaylightTime")) return; |
| 240 while ((max - min) > INTERVAL) { |
| 241 UDate mid = (min + max) / 2; |
| 242 if (tz.inDaylightTime(mid, ec) == startsInDST) { |
| 243 min = mid; |
| 244 } else { |
| 245 max = mid; |
| 246 } |
| 247 if (failure(ec, "TimeZone::inDaylightTime")) return; |
| 248 } |
| 249 min = 1000.0 * uprv_floor(min/1000.0); |
| 250 max = 1000.0 * uprv_floor(max/1000.0); |
| 251 logln(tz.getID(id) + " Before: " + min/1000 + " = " + |
| 252 dateToString(min,s,tz)); |
| 253 logln(tz.getID(id) + " After: " + max/1000 + " = " + |
| 254 dateToString(max,s,tz)); |
| 255 } |
| 256 |
| 257 void |
| 258 TimeZoneTest::testUsingBinarySearch(const TimeZone& tz, |
| 259 UDate min, UDate max, |
| 260 UDate expectedBoundary) |
| 261 { |
| 262 UErrorCode status = U_ZERO_ERROR; |
| 263 UBool startsInDST = tz.inDaylightTime(min, status); |
| 264 if (failure(status, "TimeZone::inDaylightTime")) return; |
| 265 if (tz.inDaylightTime(max, status) == startsInDST) { |
| 266 logln("Error: inDaylightTime(" + dateToString(max) + ") != " + ((!starts
InDST)?"TRUE":"FALSE")); |
| 267 return; |
| 268 } |
| 269 if (failure(status, "TimeZone::inDaylightTime")) return; |
| 270 while ((max - min) > INTERVAL) { |
| 271 UDate mid = (min + max) / 2; |
| 272 if (tz.inDaylightTime(mid, status) == startsInDST) { |
| 273 min = mid; |
| 274 } else { |
| 275 max = mid; |
| 276 } |
| 277 if (failure(status, "TimeZone::inDaylightTime")) return; |
| 278 } |
| 279 logln(UnicodeString("Binary Search Before: ") + uprv_floor(0.5 + min) + " =
" + dateToString(min)); |
| 280 logln(UnicodeString("Binary Search After: ") + uprv_floor(0.5 + max) + " =
" + dateToString(max)); |
| 281 UDate mindelta = expectedBoundary - min; |
| 282 UDate maxdelta = max - expectedBoundary; |
| 283 if (mindelta >= 0 && |
| 284 mindelta <= INTERVAL && |
| 285 maxdelta >= 0 && |
| 286 maxdelta <= INTERVAL) |
| 287 logln(UnicodeString("PASS: Expected bdry: ") + expectedBoundary + " = "
+ dateToString(expectedBoundary)); |
| 288 else |
| 289 errln(UnicodeString("FAIL: Expected bdry: ") + expectedBoundary + " = "
+ dateToString(expectedBoundary)); |
| 290 } |
| 291 |
| 292 const UDate TimeZoneTest::INTERVAL = 100; |
| 293 |
| 294 // -----------------------------------------------------------------------------
---- |
| 295 |
| 296 // ------------------------------------- |
| 297 |
| 298 /** |
| 299 * Test the offset of the PRT timezone. |
| 300 */ |
| 301 void |
| 302 TimeZoneTest::TestPRTOffset() |
| 303 { |
| 304 TimeZone* tz = TimeZone::createTimeZone("PRT"); |
| 305 if (tz == 0) { |
| 306 errln("FAIL: TimeZone(PRT) is null"); |
| 307 } |
| 308 else { |
| 309 int32_t expectedHour = -4; |
| 310 double expectedOffset = (((double)expectedHour) * millisPerHour); |
| 311 double foundOffset = tz->getRawOffset(); |
| 312 int32_t foundHour = (int32_t)foundOffset / millisPerHour; |
| 313 if (expectedOffset != foundOffset) { |
| 314 dataerrln("FAIL: Offset for PRT should be %d, found %d", expectedHour, f
oundHour); |
| 315 } else { |
| 316 logln("PASS: Offset for PRT should be %d, found %d", expectedHour, found
Hour); |
| 317 } |
| 318 } |
| 319 delete tz; |
| 320 } |
| 321 |
| 322 // ------------------------------------- |
| 323 |
| 324 /** |
| 325 * Regress a specific bug with a sequence of API calls. |
| 326 */ |
| 327 void |
| 328 TimeZoneTest::TestVariousAPI518() |
| 329 { |
| 330 UErrorCode status = U_ZERO_ERROR; |
| 331 TimeZone* time_zone = TimeZone::createTimeZone("PST"); |
| 332 UDate d = date(97, UCAL_APRIL, 30); |
| 333 UnicodeString str; |
| 334 logln("The timezone is " + time_zone->getID(str)); |
| 335 if (!time_zone->inDaylightTime(d, status)) dataerrln("FAIL: inDaylightTime r
eturned FALSE"); |
| 336 if (failure(status, "TimeZone::inDaylightTime", TRUE)) return; |
| 337 if (!time_zone->useDaylightTime()) dataerrln("FAIL: useDaylightTime returned
FALSE"); |
| 338 if (time_zone->getRawOffset() != - 8 * millisPerHour) dataerrln("FAIL: getRa
wOffset returned wrong value"); |
| 339 GregorianCalendar *gc = new GregorianCalendar(status); |
| 340 if (U_FAILURE(status)) { errln("FAIL: Couldn't create GregorianCalendar"); r
eturn; } |
| 341 gc->setTime(d, status); |
| 342 if (U_FAILURE(status)) { errln("FAIL: GregorianCalendar::setTime failed"); r
eturn; } |
| 343 if (time_zone->getOffset(gc->AD, gc->get(UCAL_YEAR, status), gc->get(UCAL_MO
NTH, status), |
| 344 gc->get(UCAL_DATE, status), (uint8_t)gc->get(UCAL_DAY_OF_WEEK, status),
0, status) != - 7 * millisPerHour) |
| 345 dataerrln("FAIL: getOffset returned wrong value"); |
| 346 if (U_FAILURE(status)) { errln("FAIL: GregorianCalendar::set failed"); retur
n; } |
| 347 delete gc; |
| 348 delete time_zone; |
| 349 } |
| 350 |
| 351 // ------------------------------------- |
| 352 |
| 353 /** |
| 354 * Test the call which retrieves the available IDs. |
| 355 */ |
| 356 void |
| 357 TimeZoneTest::TestGetAvailableIDs913() |
| 358 { |
| 359 UErrorCode ec = U_ZERO_ERROR; |
| 360 int32_t i; |
| 361 |
| 362 #ifdef U_USE_TIMEZONE_OBSOLETE_2_8 |
| 363 // Test legacy API -- remove these tests when the corresponding API goes awa
y (duh) |
| 364 int32_t numIDs = -1; |
| 365 const UnicodeString** ids = TimeZone::createAvailableIDs(numIDs); |
| 366 if (ids == 0 || numIDs < 1) { |
| 367 errln("FAIL: createAvailableIDs()"); |
| 368 } else { |
| 369 UnicodeString buf("TimeZone::createAvailableIDs() = { "); |
| 370 for(i=0; i<numIDs; ++i) { |
| 371 if (i) buf.append(", "); |
| 372 buf.append(*ids[i]); |
| 373 } |
| 374 buf.append(" } "); |
| 375 logln(buf + numIDs); |
| 376 // we own the array; the caller owns the contained strings (yuck) |
| 377 uprv_free(ids); |
| 378 } |
| 379 |
| 380 numIDs = -1; |
| 381 ids = TimeZone::createAvailableIDs(-8*U_MILLIS_PER_HOUR, numIDs); |
| 382 if (ids == 0 || numIDs < 1) { |
| 383 errln("FAIL: createAvailableIDs(-8:00)"); |
| 384 } else { |
| 385 UnicodeString buf("TimeZone::createAvailableIDs(-8:00) = { "); |
| 386 for(i=0; i<numIDs; ++i) { |
| 387 if (i) buf.append(", "); |
| 388 buf.append(*ids[i]); |
| 389 } |
| 390 buf.append(" } "); |
| 391 logln(buf + numIDs); |
| 392 // we own the array; the caller owns the contained strings (yuck) |
| 393 uprv_free(ids); |
| 394 } |
| 395 numIDs = -1; |
| 396 ids = TimeZone::createAvailableIDs("US", numIDs); |
| 397 if (ids == 0 || numIDs < 1) { |
| 398 errln("FAIL: createAvailableIDs(US) ids=%d, numIDs=%d", ids, numIDs); |
| 399 } else { |
| 400 UnicodeString buf("TimeZone::createAvailableIDs(US) = { "); |
| 401 for(i=0; i<numIDs; ++i) { |
| 402 if (i) buf.append(", "); |
| 403 buf.append(*ids[i]); |
| 404 } |
| 405 buf.append(" } "); |
| 406 logln(buf + numIDs); |
| 407 // we own the array; the caller owns the contained strings (yuck) |
| 408 uprv_free(ids); |
| 409 } |
| 410 #endif |
| 411 |
| 412 UnicodeString str; |
| 413 UnicodeString *buf = new UnicodeString("TimeZone::createEnumeration() = { ")
; |
| 414 int32_t s_length; |
| 415 StringEnumeration* s = TimeZone::createEnumeration(); |
| 416 s_length = s->count(ec); |
| 417 for (i = 0; i < s_length;++i) { |
| 418 if (i > 0) *buf += ", "; |
| 419 if ((i & 1) == 0) { |
| 420 *buf += *s->snext(ec); |
| 421 } else { |
| 422 *buf += UnicodeString(s->next(NULL, ec), ""); |
| 423 } |
| 424 |
| 425 if((i % 5) == 4) { |
| 426 // replace s with a clone of itself |
| 427 StringEnumeration *s2 = s->clone(); |
| 428 if(s2 == NULL || s_length != s2->count(ec)) { |
| 429 errln("TimezoneEnumeration.clone() failed"); |
| 430 } else { |
| 431 delete s; |
| 432 s = s2; |
| 433 } |
| 434 } |
| 435 } |
| 436 *buf += " };"; |
| 437 logln(*buf); |
| 438 |
| 439 /* Confirm that the following zones can be retrieved: The first |
| 440 * zone, the last zone, and one in-between. This tests the binary |
| 441 * search through the system zone data. |
| 442 */ |
| 443 s->reset(ec); |
| 444 int32_t middle = s_length/2; |
| 445 for (i=0; i<s_length; ++i) { |
| 446 const UnicodeString* id = s->snext(ec); |
| 447 if (i==0 || i==middle || i==(s_length-1)) { |
| 448 TimeZone *z = TimeZone::createTimeZone(*id); |
| 449 if (z == 0) { |
| 450 errln(UnicodeString("FAIL: createTimeZone(") + |
| 451 *id + ") -> 0"); |
| 452 } else if (z->getID(str) != *id) { |
| 453 errln(UnicodeString("FAIL: createTimeZone(") + |
| 454 *id + ") -> zone " + str); |
| 455 } else { |
| 456 logln(UnicodeString("OK: createTimeZone(") + |
| 457 *id + ") succeeded"); |
| 458 } |
| 459 delete z; |
| 460 } |
| 461 } |
| 462 delete s; |
| 463 |
| 464 buf->truncate(0); |
| 465 *buf += "TimeZone::createEnumeration(GMT+01:00) = { "; |
| 466 |
| 467 s = TimeZone::createEnumeration(1 * U_MILLIS_PER_HOUR); |
| 468 s_length = s->count(ec); |
| 469 for (i = 0; i < s_length;++i) { |
| 470 if (i > 0) *buf += ", "; |
| 471 *buf += *s->snext(ec); |
| 472 } |
| 473 delete s; |
| 474 *buf += " };"; |
| 475 logln(*buf); |
| 476 |
| 477 |
| 478 buf->truncate(0); |
| 479 *buf += "TimeZone::createEnumeration(US) = { "; |
| 480 |
| 481 s = TimeZone::createEnumeration("US"); |
| 482 s_length = s->count(ec); |
| 483 for (i = 0; i < s_length;++i) { |
| 484 if (i > 0) *buf += ", "; |
| 485 *buf += *s->snext(ec); |
| 486 } |
| 487 *buf += " };"; |
| 488 logln(*buf); |
| 489 |
| 490 TimeZone *tz = TimeZone::createTimeZone("PST"); |
| 491 if (tz != 0) logln("getTimeZone(PST) = " + tz->getID(str)); |
| 492 else errln("FAIL: getTimeZone(PST) = null"); |
| 493 delete tz; |
| 494 tz = TimeZone::createTimeZone("America/Los_Angeles"); |
| 495 if (tz != 0) logln("getTimeZone(America/Los_Angeles) = " + tz->getID(str)); |
| 496 else errln("FAIL: getTimeZone(PST) = null"); |
| 497 delete tz; |
| 498 |
| 499 // @bug 4096694 |
| 500 tz = TimeZone::createTimeZone("NON_EXISTENT"); |
| 501 UnicodeString temp; |
| 502 if (tz == 0) |
| 503 errln("FAIL: getTimeZone(NON_EXISTENT) = null"); |
| 504 else if (tz->getID(temp) != "GMT") |
| 505 errln("FAIL: getTimeZone(NON_EXISTENT) = " + temp); |
| 506 delete tz; |
| 507 |
| 508 delete buf; |
| 509 delete s; |
| 510 } |
| 511 |
| 512 |
| 513 /** |
| 514 * NOTE: As of ICU 2.8, this test confirms that the "tz.alias" |
| 515 * file, used to build ICU alias zones, is working. It also |
| 516 * looks at some genuine Olson compatibility IDs. [aliu] |
| 517 * |
| 518 * This test is problematic. It should really just confirm that |
| 519 * the list of compatibility zone IDs exist and are somewhat |
| 520 * meaningful (that is, they aren't all aliases of GMT). It goes a |
| 521 * bit further -- it hard-codes expectations about zone behavior, |
| 522 * when in fact zones are redefined quite frequently. ICU's build |
| 523 * process means that it is easy to update ICU to contain the |
| 524 * latest Olson zone data, but if a zone tested here changes, then |
| 525 * this test will fail. I have updated the test for 1999j data, |
| 526 * but further updates will probably be required. Note that some |
| 527 * of the concerts listed below no longer apply -- in particular, |
| 528 * we do NOT overwrite real UNIX zones with 3-letter IDs. There |
| 529 * are two points of overlap as of 1999j: MET and EET. These are |
| 530 * both real UNIX zones, so we just use the official |
| 531 * definition. This test has been updated to reflect this. |
| 532 * 12/3/99 aliu |
| 533 * |
| 534 * Added tests for additional zones and aliases from the icuzones file. |
| 535 * Markus Scherer 2006-nov-06 |
| 536 * |
| 537 * [srl - from java - 7/5/1998] |
| 538 * @bug 4130885 |
| 539 * Certain short zone IDs, used since 1.1.x, are incorrect. |
| 540 * |
| 541 * The worst of these is: |
| 542 * |
| 543 * "CAT" (Central African Time) should be GMT+2:00, but instead returns a |
| 544 * zone at GMT-1:00. The zone at GMT-1:00 should be called EGT, CVT, EGST, |
| 545 * or AZOST, depending on which zone is meant, but in no case is it CAT. |
| 546 * |
| 547 * Other wrong zone IDs: |
| 548 * |
| 549 * ECT (European Central Time) GMT+1:00: ECT is Ecuador Time, |
| 550 * GMT-5:00. European Central time is abbreviated CEST. |
| 551 * |
| 552 * SST (Solomon Island Time) GMT+11:00. SST is actually Samoa Standard Time, |
| 553 * GMT-11:00. Solomon Island time is SBT. |
| 554 * |
| 555 * NST (New Zealand Time) GMT+12:00. NST is the abbreviation for |
| 556 * Newfoundland Standard Time, GMT-3:30. New Zealanders use NZST. |
| 557 * |
| 558 * AST (Alaska Standard Time) GMT-9:00. [This has already been noted in |
| 559 * another bug.] It should be "AKST". AST is Atlantic Standard Time, |
| 560 * GMT-4:00. |
| 561 * |
| 562 * PNT (Phoenix Time) GMT-7:00. PNT usually means Pitcairn Time, |
| 563 * GMT-8:30. There is no standard abbreviation for Phoenix time, as distinct |
| 564 * from MST with daylight savings. |
| 565 * |
| 566 * In addition to these problems, a number of zones are FAKE. That is, they |
| 567 * don't match what people use in the real world. |
| 568 * |
| 569 * FAKE zones: |
| 570 * |
| 571 * EET (should be EEST) |
| 572 * ART (should be EEST) |
| 573 * MET (should be IRST) |
| 574 * NET (should be AMST) |
| 575 * PLT (should be PKT) |
| 576 * BST (should be BDT) |
| 577 * VST (should be ICT) |
| 578 * CTT (should be CST) + |
| 579 * ACT (should be CST) + |
| 580 * AET (should be EST) + |
| 581 * MIT (should be WST) + |
| 582 * IET (should be EST) + |
| 583 * PRT (should be AST) + |
| 584 * CNT (should be NST) |
| 585 * AGT (should be ARST) |
| 586 * BET (should be EST) + |
| 587 * |
| 588 * + A zone with the correct name already exists and means something |
| 589 * else. E.g., EST usually indicates the US Eastern zone, so it cannot be |
| 590 * used for Brazil (BET). |
| 591 */ |
| 592 void TimeZoneTest::TestShortZoneIDs() |
| 593 { |
| 594 UErrorCode status = U_ZERO_ERROR; |
| 595 |
| 596 // This test case is tzdata version sensitive. |
| 597 UBool isNonReferenceTzdataVersion = FALSE; |
| 598 const char *tzdataVer = TimeZone::getTZDataVersion(status); |
| 599 if (failure(status, "getTZDataVersion")) return; |
| 600 if (uprv_strcmp(tzdataVer, TimeZoneTest::REFERENCE_DATA_VERSION) != 0) { |
| 601 // Note: We want to display a warning message here if |
| 602 // REFERENCE_DATA_VERSION is out of date - so we |
| 603 // do not forget to update the value before GA. |
| 604 isNonReferenceTzdataVersion = TRUE; |
| 605 logln(UnicodeString("Warning: Active tzdata version (") + tzdataVer + |
| 606 ") does not match the reference tzdata version (" |
| 607 + REFERENCE_DATA_VERSION + ") for this test case data."); |
| 608 } |
| 609 |
| 610 // Note: useDaylightTime returns true if DST is observed |
| 611 // in the time zone in the current calendar year. The test |
| 612 // data is valid for the date after the reference year below. |
| 613 // If system clock is before the year, some test cases may |
| 614 // fail. |
| 615 GregorianCalendar cal(*TimeZone::getGMT(), status); |
| 616 if (failure(status, "GregorianCalendar")) return; |
| 617 cal.set(TimeZoneTest::REFERENCE_YEAR, UCAL_JANUARY, 2); // day 2 in GMT |
| 618 |
| 619 UBool isDateBeforeReferenceYear = ucal_getNow() < cal.getTime(status); |
| 620 if (failure(status, "Calendar::getTime")) return; |
| 621 if (isDateBeforeReferenceYear) { |
| 622 logln("Warning: Past time is set to the system clock. Some test cases m
ay not return expected results."); |
| 623 } |
| 624 |
| 625 int32_t i; |
| 626 // Create a small struct to hold the array |
| 627 struct |
| 628 { |
| 629 const char *id; |
| 630 int32_t offset; |
| 631 UBool daylight; |
| 632 } |
| 633 kReferenceList [] = |
| 634 { |
| 635 {"MIT", -660, FALSE}, |
| 636 {"HST", -600, FALSE}, |
| 637 {"AST", -540, TRUE}, |
| 638 {"PST", -480, TRUE}, |
| 639 {"PNT", -420, FALSE}, |
| 640 {"MST", -420, FALSE}, // updated Aug 2003 aliu |
| 641 {"CST", -360, TRUE}, |
| 642 {"IET", -300, TRUE}, // updated Jan 2006 srl |
| 643 {"EST", -300, FALSE}, // updated Aug 2003 aliu |
| 644 {"PRT", -240, FALSE}, |
| 645 {"CNT", -210, TRUE}, |
| 646 {"AGT", -180, TRUE}, // updated by tzdata2007k |
| 647 {"BET", -180, TRUE}, |
| 648 {"GMT", 0, FALSE}, |
| 649 {"UTC", 0, FALSE}, // ** srl: seems broken in C++ |
| 650 {"ECT", 60, TRUE}, |
| 651 {"MET", 60, TRUE}, // updated 12/3/99 aliu |
| 652 {"ART", 120, TRUE}, |
| 653 {"EET", 120, TRUE}, |
| 654 {"CAT", 120, FALSE}, // Africa/Harare |
| 655 {"EAT", 180, FALSE}, |
| 656 {"NET", 240, TRUE}, // updated 12/3/99 aliu |
| 657 {"PLT", 300, FALSE}, // updated by 2008c - no DST after 2008 |
| 658 {"IST", 330, FALSE}, |
| 659 {"BST", 360, FALSE}, |
| 660 {"VST", 420, FALSE}, |
| 661 {"CTT", 480, FALSE}, // updated Aug 2003 aliu |
| 662 {"JST", 540, FALSE}, |
| 663 {"ACT", 570, FALSE}, // updated Aug 2003 aliu |
| 664 {"AET", 600, TRUE}, |
| 665 {"SST", 660, FALSE}, |
| 666 {"NST", 720, TRUE}, // Pacific/Auckland |
| 667 |
| 668 // From icuzones: |
| 669 {"Etc/Unknown", 0, FALSE}, |
| 670 |
| 671 {"SystemV/AST4ADT", -240, TRUE}, |
| 672 {"SystemV/EST5EDT", -300, TRUE}, |
| 673 {"SystemV/CST6CDT", -360, TRUE}, |
| 674 {"SystemV/MST7MDT", -420, TRUE}, |
| 675 {"SystemV/PST8PDT", -480, TRUE}, |
| 676 {"SystemV/YST9YDT", -540, TRUE}, |
| 677 {"SystemV/AST4", -240, FALSE}, |
| 678 {"SystemV/EST5", -300, FALSE}, |
| 679 {"SystemV/CST6", -360, FALSE}, |
| 680 {"SystemV/MST7", -420, FALSE}, |
| 681 {"SystemV/PST8", -480, FALSE}, |
| 682 {"SystemV/YST9", -540, FALSE}, |
| 683 {"SystemV/HST10", -600, FALSE}, |
| 684 |
| 685 {"",0,FALSE} |
| 686 }; |
| 687 |
| 688 for(i=0;kReferenceList[i].id[0];i++) { |
| 689 UnicodeString itsID(kReferenceList[i].id); |
| 690 UBool ok = TRUE; |
| 691 // Check existence. |
| 692 TimeZone *tz = TimeZone::createTimeZone(itsID); |
| 693 if (!tz || (kReferenceList[i].offset != 0 && *tz == *TimeZone::getGMT())
) { |
| 694 errln("FAIL: Time Zone " + itsID + " does not exist!"); |
| 695 continue; |
| 696 } |
| 697 |
| 698 // Check daylight usage. |
| 699 UBool usesDaylight = tz->useDaylightTime(); |
| 700 if (usesDaylight != kReferenceList[i].daylight) { |
| 701 if (isNonReferenceTzdataVersion || isDateBeforeReferenceYear) { |
| 702 logln("Warning: Time Zone " + itsID + " use daylight is " + |
| 703 (usesDaylight?"TRUE":"FALSE") + |
| 704 " but it should be " + |
| 705 ((kReferenceList[i].daylight)?"TRUE":"FALSE")); |
| 706 } else { |
| 707 errln("FAIL: Time Zone " + itsID + " use daylight is " + |
| 708 (usesDaylight?"TRUE":"FALSE") + |
| 709 " but it should be " + |
| 710 ((kReferenceList[i].daylight)?"TRUE":"FALSE")); |
| 711 } |
| 712 ok = FALSE; |
| 713 } |
| 714 |
| 715 // Check offset |
| 716 int32_t offsetInMinutes = tz->getRawOffset()/60000; |
| 717 if (offsetInMinutes != kReferenceList[i].offset) { |
| 718 if (isNonReferenceTzdataVersion || isDateBeforeReferenceYear) { |
| 719 logln("FAIL: Time Zone " + itsID + " raw offset is " + |
| 720 offsetInMinutes + |
| 721 " but it should be " + kReferenceList[i].offset); |
| 722 } else { |
| 723 errln("FAIL: Time Zone " + itsID + " raw offset is " + |
| 724 offsetInMinutes + |
| 725 " but it should be " + kReferenceList[i].offset); |
| 726 } |
| 727 ok = FALSE; |
| 728 } |
| 729 |
| 730 if (ok) { |
| 731 logln("OK: " + itsID + |
| 732 " useDaylightTime() & getRawOffset() as expected"); |
| 733 } |
| 734 delete tz; |
| 735 } |
| 736 |
| 737 |
| 738 // OK now test compat |
| 739 logln("Testing for compatibility zones"); |
| 740 |
| 741 const char* compatibilityMap[] = { |
| 742 // This list is copied from tz.alias. If tz.alias |
| 743 // changes, this list must be updated. Current as of Mar 2007 |
| 744 "ACT", "Australia/Darwin", |
| 745 "AET", "Australia/Sydney", |
| 746 "AGT", "America/Buenos_Aires", |
| 747 "ART", "Africa/Cairo", |
| 748 "AST", "America/Anchorage", |
| 749 "BET", "America/Sao_Paulo", |
| 750 "BST", "Asia/Dhaka", // # spelling changed in 2000h; was Asia/Dacca |
| 751 "CAT", "Africa/Harare", |
| 752 "CNT", "America/St_Johns", |
| 753 "CST", "America/Chicago", |
| 754 "CTT", "Asia/Shanghai", |
| 755 "EAT", "Africa/Addis_Ababa", |
| 756 "ECT", "Europe/Paris", |
| 757 // EET Europe/Istanbul # EET is a standard UNIX zone |
| 758 // "EST", "America/New_York", # Defined as -05:00 |
| 759 // "HST", "Pacific/Honolulu", # Defined as -10:00 |
| 760 "IET", "America/Indianapolis", |
| 761 "IST", "Asia/Calcutta", |
| 762 "JST", "Asia/Tokyo", |
| 763 // MET Asia/Tehran # MET is a standard UNIX zone |
| 764 "MIT", "Pacific/Apia", |
| 765 // "MST", "America/Denver", # Defined as -07:00 |
| 766 "NET", "Asia/Yerevan", |
| 767 "NST", "Pacific/Auckland", |
| 768 "PLT", "Asia/Karachi", |
| 769 "PNT", "America/Phoenix", |
| 770 "PRT", "America/Puerto_Rico", |
| 771 "PST", "America/Los_Angeles", |
| 772 "SST", "Pacific/Guadalcanal", |
| 773 "UTC", "Etc/GMT", |
| 774 "VST", "Asia/Saigon", |
| 775 "","","" |
| 776 }; |
| 777 |
| 778 for (i=0;*compatibilityMap[i];i+=2) { |
| 779 UnicodeString itsID; |
| 780 |
| 781 const char *zone1 = compatibilityMap[i]; |
| 782 const char *zone2 = compatibilityMap[i+1]; |
| 783 |
| 784 TimeZone *tz1 = TimeZone::createTimeZone(zone1); |
| 785 TimeZone *tz2 = TimeZone::createTimeZone(zone2); |
| 786 |
| 787 if (!tz1) { |
| 788 errln(UnicodeString("FAIL: Could not find short ID zone ") + zone1); |
| 789 } |
| 790 if (!tz2) { |
| 791 errln(UnicodeString("FAIL: Could not find long ID zone ") + zone2); |
| 792 } |
| 793 |
| 794 if (tz1 && tz2) { |
| 795 // make NAME same so comparison will only look at the rest |
| 796 tz2->setID(tz1->getID(itsID)); |
| 797 |
| 798 if (*tz1 != *tz2) { |
| 799 errln("FAIL: " + UnicodeString(zone1) + |
| 800 " != " + UnicodeString(zone2)); |
| 801 } else { |
| 802 logln("OK: " + UnicodeString(zone1) + |
| 803 " == " + UnicodeString(zone2)); |
| 804 } |
| 805 } |
| 806 |
| 807 delete tz1; |
| 808 delete tz2; |
| 809 } |
| 810 } |
| 811 |
| 812 |
| 813 /** |
| 814 * Utility function for TestCustomParse |
| 815 */ |
| 816 UnicodeString& TimeZoneTest::formatOffset(int32_t offset, UnicodeString &rv) { |
| 817 rv.remove(); |
| 818 UChar sign = 0x002B; |
| 819 if (offset < 0) { |
| 820 sign = 0x002D; |
| 821 offset = -offset; |
| 822 } |
| 823 |
| 824 int32_t s = offset % 60; |
| 825 offset /= 60; |
| 826 int32_t m = offset % 60; |
| 827 int32_t h = offset / 60; |
| 828 |
| 829 rv += (UChar)(sign); |
| 830 if (h >= 10) { |
| 831 rv += (UChar)(0x0030 + (h/10)); |
| 832 } else { |
| 833 rv += (UChar)0x0030; |
| 834 } |
| 835 rv += (UChar)(0x0030 + (h%10)); |
| 836 |
| 837 rv += (UChar)0x003A; /* ':' */ |
| 838 if (m >= 10) { |
| 839 rv += (UChar)(0x0030 + (m/10)); |
| 840 } else { |
| 841 rv += (UChar)0x0030; |
| 842 } |
| 843 rv += (UChar)(0x0030 + (m%10)); |
| 844 |
| 845 if (s) { |
| 846 rv += (UChar)0x003A; /* ':' */ |
| 847 if (s >= 10) { |
| 848 rv += (UChar)(0x0030 + (s/10)); |
| 849 } else { |
| 850 rv += (UChar)0x0030; |
| 851 } |
| 852 rv += (UChar)(0x0030 + (s%10)); |
| 853 } |
| 854 return rv; |
| 855 } |
| 856 |
| 857 /** |
| 858 * Utility function for TestCustomParse, generating time zone ID |
| 859 * string for the give offset. |
| 860 */ |
| 861 UnicodeString& TimeZoneTest::formatTZID(int32_t offset, UnicodeString &rv) { |
| 862 rv.remove(); |
| 863 UChar sign = 0x002B; |
| 864 if (offset < 0) { |
| 865 sign = 0x002D; |
| 866 offset = -offset; |
| 867 } |
| 868 |
| 869 int32_t s = offset % 60; |
| 870 offset /= 60; |
| 871 int32_t m = offset % 60; |
| 872 int32_t h = offset / 60; |
| 873 |
| 874 rv += "GMT"; |
| 875 rv += (UChar)(sign); |
| 876 if (h >= 10) { |
| 877 rv += (UChar)(0x0030 + (h/10)); |
| 878 } else { |
| 879 rv += (UChar)0x0030; |
| 880 } |
| 881 rv += (UChar)(0x0030 + (h%10)); |
| 882 rv += (UChar)0x003A; |
| 883 if (m >= 10) { |
| 884 rv += (UChar)(0x0030 + (m/10)); |
| 885 } else { |
| 886 rv += (UChar)0x0030; |
| 887 } |
| 888 rv += (UChar)(0x0030 + (m%10)); |
| 889 |
| 890 if (s) { |
| 891 rv += (UChar)0x003A; |
| 892 if (s >= 10) { |
| 893 rv += (UChar)(0x0030 + (s/10)); |
| 894 } else { |
| 895 rv += (UChar)0x0030; |
| 896 } |
| 897 rv += (UChar)(0x0030 + (s%10)); |
| 898 } |
| 899 return rv; |
| 900 } |
| 901 |
| 902 /** |
| 903 * As part of the VM fix (see CCC approved RFE 4028006, bug |
| 904 * 4044013), TimeZone.getTimeZone() has been modified to recognize |
| 905 * generic IDs of the form GMT[+-]hh:mm, GMT[+-]hhmm, and |
| 906 * GMT[+-]hh. Test this behavior here. |
| 907 * |
| 908 * @bug 4044013 |
| 909 */ |
| 910 void TimeZoneTest::TestCustomParse() |
| 911 { |
| 912 int32_t i; |
| 913 const int32_t kUnparseable = 604800; // the number of seconds in a week. Mor
e than any offset should be. |
| 914 |
| 915 struct |
| 916 { |
| 917 const char *customId; |
| 918 int32_t expectedOffset; |
| 919 } |
| 920 kData[] = |
| 921 { |
| 922 // ID Expected offset in seconds |
| 923 {"GMT", kUnparseable}, //Isn't custom. [returns normal GMT] |
| 924 {"GMT-YOUR.AD.HERE", kUnparseable}, |
| 925 {"GMT0", kUnparseable}, |
| 926 {"GMT+0", (0)}, |
| 927 {"GMT+1", (1*60*60)}, |
| 928 {"GMT-0030", (-30*60)}, |
| 929 {"GMT+15:99", kUnparseable}, |
| 930 {"GMT+", kUnparseable}, |
| 931 {"GMT-", kUnparseable}, |
| 932 {"GMT+0:", kUnparseable}, |
| 933 {"GMT-:", kUnparseable}, |
| 934 {"GMT-YOUR.AD.HERE", kUnparseable}, |
| 935 {"GMT+0010", (10*60)}, // Interpret this as 00:10 |
| 936 {"GMT-10", (-10*60*60)}, |
| 937 {"GMT+30", kUnparseable}, |
| 938 {"GMT-3:30", (-(3*60+30)*60)}, |
| 939 {"GMT-230", (-(2*60+30)*60)}, |
| 940 {"GMT+05:13:05", ((5*60+13)*60+5)}, |
| 941 {"GMT-71023", (-((7*60+10)*60+23))}, |
| 942 {"GMT+01:23:45:67", kUnparseable}, |
| 943 {"GMT+01:234", kUnparseable}, |
| 944 {"GMT-2:31:123", kUnparseable}, |
| 945 {"GMT+3:75", kUnparseable}, |
| 946 {"GMT-01010101", kUnparseable}, |
| 947 {0, 0} |
| 948 }; |
| 949 |
| 950 for (i=0; kData[i].customId != 0; i++) { |
| 951 UnicodeString id(kData[i].customId); |
| 952 int32_t exp = kData[i].expectedOffset; |
| 953 TimeZone *zone = TimeZone::createTimeZone(id); |
| 954 UnicodeString itsID, temp; |
| 955 |
| 956 if (dynamic_cast<OlsonTimeZone *>(zone) != NULL) { |
| 957 logln(id + " -> Olson time zone"); |
| 958 } else { |
| 959 zone->getID(itsID); |
| 960 int32_t ioffset = zone->getRawOffset()/1000; |
| 961 UnicodeString offset, expectedID; |
| 962 formatOffset(ioffset, offset); |
| 963 formatTZID(ioffset, expectedID); |
| 964 logln(id + " -> " + itsID + " " + offset); |
| 965 if (exp == kUnparseable && itsID != "GMT") { |
| 966 errln("Expected parse failure for " + id + |
| 967 ", got offset of " + offset + |
| 968 ", id " + itsID); |
| 969 } |
| 970 // JDK 1.3 creates custom zones with the ID "Custom" |
| 971 // JDK 1.4 creates custom zones with IDs of the form "GMT+02:00" |
| 972 // ICU creates custom zones with IDs of the form "GMT+02:00" |
| 973 else if (exp != kUnparseable && (ioffset != exp || itsID != expected
ID)) { |
| 974 dataerrln("Expected offset of " + formatOffset(exp, temp) + |
| 975 ", id " + expectedID + |
| 976 ", for " + id + |
| 977 ", got offset of " + offset + |
| 978 ", id " + itsID); |
| 979 } |
| 980 } |
| 981 delete zone; |
| 982 } |
| 983 } |
| 984 |
| 985 void |
| 986 TimeZoneTest::TestAliasedNames() |
| 987 { |
| 988 struct { |
| 989 const char *from; |
| 990 const char *to; |
| 991 } kData[] = { |
| 992 /* Generated by org.unicode.cldr.tool.CountItems */ |
| 993 |
| 994 /* zoneID, canonical zoneID */ |
| 995 {"Africa/Timbuktu", "Africa/Bamako"}, |
| 996 {"America/Argentina/Buenos_Aires", "America/Buenos_Aires"}, |
| 997 {"America/Argentina/Catamarca", "America/Catamarca"}, |
| 998 {"America/Argentina/ComodRivadavia", "America/Catamarca"}, |
| 999 {"America/Argentina/Cordoba", "America/Cordoba"}, |
| 1000 {"America/Argentina/Jujuy", "America/Jujuy"}, |
| 1001 {"America/Argentina/Mendoza", "America/Mendoza"}, |
| 1002 {"America/Atka", "America/Adak"}, |
| 1003 {"America/Ensenada", "America/Tijuana"}, |
| 1004 {"America/Fort_Wayne", "America/Indiana/Indianapolis"}, |
| 1005 {"America/Indianapolis", "America/Indiana/Indianapolis"}, |
| 1006 {"America/Knox_IN", "America/Indiana/Knox"}, |
| 1007 {"America/Louisville", "America/Kentucky/Louisville"}, |
| 1008 {"America/Porto_Acre", "America/Rio_Branco"}, |
| 1009 {"America/Rosario", "America/Cordoba"}, |
| 1010 {"America/Virgin", "America/St_Thomas"}, |
| 1011 {"Asia/Ashkhabad", "Asia/Ashgabat"}, |
| 1012 {"Asia/Chungking", "Asia/Chongqing"}, |
| 1013 {"Asia/Dacca", "Asia/Dhaka"}, |
| 1014 {"Asia/Istanbul", "Europe/Istanbul"}, |
| 1015 {"Asia/Macao", "Asia/Macau"}, |
| 1016 {"Asia/Tel_Aviv", "Asia/Jerusalem"}, |
| 1017 {"Asia/Thimbu", "Asia/Thimphu"}, |
| 1018 {"Asia/Ujung_Pandang", "Asia/Makassar"}, |
| 1019 {"Asia/Ulan_Bator", "Asia/Ulaanbaatar"}, |
| 1020 {"Australia/ACT", "Australia/Sydney"}, |
| 1021 {"Australia/Canberra", "Australia/Sydney"}, |
| 1022 {"Australia/LHI", "Australia/Lord_Howe"}, |
| 1023 {"Australia/NSW", "Australia/Sydney"}, |
| 1024 {"Australia/North", "Australia/Darwin"}, |
| 1025 {"Australia/Queensland", "Australia/Brisbane"}, |
| 1026 {"Australia/South", "Australia/Adelaide"}, |
| 1027 {"Australia/Tasmania", "Australia/Hobart"}, |
| 1028 {"Australia/Victoria", "Australia/Melbourne"}, |
| 1029 {"Australia/West", "Australia/Perth"}, |
| 1030 {"Australia/Yancowinna", "Australia/Broken_Hill"}, |
| 1031 {"Brazil/Acre", "America/Rio_Branco"}, |
| 1032 {"Brazil/DeNoronha", "America/Noronha"}, |
| 1033 {"Brazil/East", "America/Sao_Paulo"}, |
| 1034 {"Brazil/West", "America/Manaus"}, |
| 1035 {"Canada/Atlantic", "America/Halifax"}, |
| 1036 {"Canada/Central", "America/Winnipeg"}, |
| 1037 {"Canada/East-Saskatchewan", "America/Regina"}, |
| 1038 {"Canada/Eastern", "America/Toronto"}, |
| 1039 {"Canada/Mountain", "America/Edmonton"}, |
| 1040 {"Canada/Newfoundland", "America/St_Johns"}, |
| 1041 {"Canada/Pacific", "America/Vancouver"}, |
| 1042 {"Canada/Saskatchewan", "America/Regina"}, |
| 1043 {"Canada/Yukon", "America/Whitehorse"}, |
| 1044 {"Chile/Continental", "America/Santiago"}, |
| 1045 {"Chile/EasterIsland", "Pacific/Easter"}, |
| 1046 {"Cuba", "America/Havana"}, |
| 1047 {"Egypt", "Africa/Cairo"}, |
| 1048 {"Eire", "Europe/Dublin"}, |
| 1049 {"Etc/GMT+0", "Etc/GMT"}, |
| 1050 {"Etc/GMT-0", "Etc/GMT"}, |
| 1051 {"Etc/GMT0", "Etc/GMT"}, |
| 1052 {"Etc/Greenwich", "Etc/GMT"}, |
| 1053 {"Etc/UCT", "Etc/GMT"}, |
| 1054 {"Etc/UTC", "Etc/GMT"}, |
| 1055 {"Etc/Universal", "Etc/GMT"}, |
| 1056 {"Etc/Zulu", "Etc/GMT"}, |
| 1057 {"Europe/Belfast", "Europe/London"}, |
| 1058 {"Europe/Nicosia", "Asia/Nicosia"}, |
| 1059 {"Europe/Tiraspol", "Europe/Chisinau"}, |
| 1060 {"GB", "Europe/London"}, |
| 1061 {"GB-Eire", "Europe/London"}, |
| 1062 {"GMT", "Etc/GMT"}, |
| 1063 {"GMT+0", "Etc/GMT"}, |
| 1064 {"GMT-0", "Etc/GMT"}, |
| 1065 {"GMT0", "Etc/GMT"}, |
| 1066 {"Greenwich", "Etc/GMT"}, |
| 1067 {"Hongkong", "Asia/Hong_Kong"}, |
| 1068 {"Iceland", "Atlantic/Reykjavik"}, |
| 1069 {"Iran", "Asia/Tehran"}, |
| 1070 {"Israel", "Asia/Jerusalem"}, |
| 1071 {"Jamaica", "America/Jamaica"}, |
| 1072 {"Japan", "Asia/Tokyo"}, |
| 1073 {"Kwajalein", "Pacific/Kwajalein"}, |
| 1074 {"Libya", "Africa/Tripoli"}, |
| 1075 {"Mexico/BajaNorte", "America/Tijuana"}, |
| 1076 {"Mexico/BajaSur", "America/Mazatlan"}, |
| 1077 {"Mexico/General", "America/Mexico_City"}, |
| 1078 {"NZ", "Pacific/Auckland"}, |
| 1079 {"NZ-CHAT", "Pacific/Chatham"}, |
| 1080 {"Navajo", "America/Shiprock"}, |
| 1081 {"PRC", "Asia/Shanghai"}, |
| 1082 {"Pacific/Samoa", "Pacific/Pago_Pago"}, |
| 1083 {"Pacific/Yap", "Pacific/Truk"}, |
| 1084 {"Poland", "Europe/Warsaw"}, |
| 1085 {"Portugal", "Europe/Lisbon"}, |
| 1086 {"ROC", "Asia/Taipei"}, |
| 1087 {"ROK", "Asia/Seoul"}, |
| 1088 {"Singapore", "Asia/Singapore"}, |
| 1089 {"Turkey", "Europe/Istanbul"}, |
| 1090 {"UCT", "Etc/GMT"}, |
| 1091 {"US/Alaska", "America/Anchorage"}, |
| 1092 {"US/Aleutian", "America/Adak"}, |
| 1093 {"US/Arizona", "America/Phoenix"}, |
| 1094 {"US/Central", "America/Chicago"}, |
| 1095 {"US/East-Indiana", "America/Indiana/Indianapolis"}, |
| 1096 {"US/Eastern", "America/New_York"}, |
| 1097 {"US/Hawaii", "Pacific/Honolulu"}, |
| 1098 {"US/Indiana-Starke", "America/Indiana/Knox"}, |
| 1099 {"US/Michigan", "America/Detroit"}, |
| 1100 {"US/Mountain", "America/Denver"}, |
| 1101 {"US/Pacific", "America/Los_Angeles"}, |
| 1102 {"US/Pacific-New", "America/Los_Angeles"}, |
| 1103 {"US/Samoa", "Pacific/Pago_Pago"}, |
| 1104 {"UTC", "Etc/GMT"}, |
| 1105 {"Universal", "Etc/GMT"}, |
| 1106 {"W-SU", "Europe/Moscow"}, |
| 1107 {"Zulu", "Etc/GMT"}, |
| 1108 /* Total: 113 */ |
| 1109 |
| 1110 }; |
| 1111 |
| 1112 TimeZone::EDisplayType styles[] = { TimeZone::SHORT, TimeZone::LONG }; |
| 1113 UBool useDst[] = { FALSE, TRUE }; |
| 1114 int32_t noLoc = uloc_countAvailable(); |
| 1115 |
| 1116 int32_t i, j, k, loc; |
| 1117 UnicodeString fromName, toName; |
| 1118 TimeZone *from = NULL, *to = NULL; |
| 1119 for(i = 0; i < (int32_t)(sizeof(kData)/sizeof(kData[0])); i++) { |
| 1120 from = TimeZone::createTimeZone(kData[i].from); |
| 1121 to = TimeZone::createTimeZone(kData[i].to); |
| 1122 if(!from->hasSameRules(*to)) { |
| 1123 errln("different at %i\n", i); |
| 1124 } |
| 1125 if(!quick) { |
| 1126 for(loc = 0; loc < noLoc; loc++) { |
| 1127 const char* locale = uloc_getAvailable(loc); |
| 1128 for(j = 0; j < (int32_t)(sizeof(styles)/sizeof(styles[0])); j++)
{ |
| 1129 for(k = 0; k < (int32_t)(sizeof(useDst)/sizeof(useDst[0]));
k++) { |
| 1130 fromName.remove(); |
| 1131 toName.remove(); |
| 1132 from->getDisplayName(useDst[k], styles[j],locale, fromNa
me); |
| 1133 to->getDisplayName(useDst[k], styles[j], locale, toName)
; |
| 1134 if(fromName.compare(toName) != 0) { |
| 1135 errln("Fail: Expected "+toName+" but got " + prettif
y(fromName) |
| 1136 + " for locale: " + locale + " index: "+ loc |
| 1137 + " to id "+ kData[i].to |
| 1138 + " from id " + kData[i].from); |
| 1139 } |
| 1140 } |
| 1141 } |
| 1142 } |
| 1143 } else { |
| 1144 fromName.remove(); |
| 1145 toName.remove(); |
| 1146 from->getDisplayName(fromName); |
| 1147 to->getDisplayName(toName); |
| 1148 if(fromName.compare(toName) != 0) { |
| 1149 errln("Fail: Expected "+toName+" but got " + fromName); |
| 1150 } |
| 1151 } |
| 1152 delete from; |
| 1153 delete to; |
| 1154 } |
| 1155 } |
| 1156 |
| 1157 /** |
| 1158 * Test the basic functionality of the getDisplayName() API. |
| 1159 * |
| 1160 * @bug 4112869 |
| 1161 * @bug 4028006 |
| 1162 * |
| 1163 * See also API change request A41. |
| 1164 * |
| 1165 * 4/21/98 - make smarter, so the test works if the ext resources |
| 1166 * are present or not. |
| 1167 */ |
| 1168 void |
| 1169 TimeZoneTest::TestDisplayName() |
| 1170 { |
| 1171 UErrorCode status = U_ZERO_ERROR; |
| 1172 int32_t i; |
| 1173 TimeZone *zone = TimeZone::createTimeZone("PST"); |
| 1174 UnicodeString name; |
| 1175 zone->getDisplayName(Locale::getEnglish(), name); |
| 1176 logln("PST->" + name); |
| 1177 if (name.compare("Pacific Standard Time") != 0) |
| 1178 dataerrln("Fail: Expected \"Pacific Standard Time\" but got " + name); |
| 1179 |
| 1180 //***************************************************************** |
| 1181 // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES |
| 1182 // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES |
| 1183 // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES |
| 1184 //***************************************************************** |
| 1185 struct |
| 1186 { |
| 1187 UBool useDst; |
| 1188 TimeZone::EDisplayType style; |
| 1189 const char *expect; |
| 1190 } kData[] = { |
| 1191 {FALSE, TimeZone::SHORT, "PST"}, |
| 1192 {TRUE, TimeZone::SHORT, "PDT"}, |
| 1193 {FALSE, TimeZone::LONG, "Pacific Standard Time"}, |
| 1194 {TRUE, TimeZone::LONG, "Pacific Daylight Time"}, |
| 1195 |
| 1196 {FALSE, TimeZone::SHORT_GENERIC, "PT"}, |
| 1197 {TRUE, TimeZone::SHORT_GENERIC, "PT"}, |
| 1198 {FALSE, TimeZone::LONG_GENERIC, "Pacific Time"}, |
| 1199 {TRUE, TimeZone::LONG_GENERIC, "Pacific Time"}, |
| 1200 |
| 1201 {FALSE, TimeZone::SHORT_GMT, "-0800"}, |
| 1202 {TRUE, TimeZone::SHORT_GMT, "-0700"}, |
| 1203 {FALSE, TimeZone::LONG_GMT, "GMT-08:00"}, |
| 1204 {TRUE, TimeZone::LONG_GMT, "GMT-07:00"}, |
| 1205 |
| 1206 {FALSE, TimeZone::SHORT_COMMONLY_USED, "PST"}, |
| 1207 {TRUE, TimeZone::SHORT_COMMONLY_USED, "PDT"}, |
| 1208 {FALSE, TimeZone::GENERIC_LOCATION, "United States (Los Angeles)"}, |
| 1209 {TRUE, TimeZone::GENERIC_LOCATION, "United States (Los Angeles)"}, |
| 1210 |
| 1211 {FALSE, TimeZone::LONG, ""} |
| 1212 }; |
| 1213 |
| 1214 for (i=0; kData[i].expect[0] != '\0'; i++) |
| 1215 { |
| 1216 name.remove(); |
| 1217 name = zone->getDisplayName(kData[i].useDst, |
| 1218 kData[i].style, |
| 1219 Locale::getEnglish(), name); |
| 1220 if (name.compare(kData[i].expect) != 0) |
| 1221 dataerrln("Fail: Expected " + UnicodeString(kData[i].expect) + "; go
t " + name); |
| 1222 logln("PST [with options]->" + name); |
| 1223 } |
| 1224 for (i=0; kData[i].expect[0] != '\0'; i++) |
| 1225 { |
| 1226 name.remove(); |
| 1227 name = zone->getDisplayName(kData[i].useDst, |
| 1228 kData[i].style, name); |
| 1229 if (name.compare(kData[i].expect) != 0) |
| 1230 dataerrln("Fail: Expected " + UnicodeString(kData[i].expect) + "; go
t " + name); |
| 1231 logln("PST [with options]->" + name); |
| 1232 } |
| 1233 |
| 1234 |
| 1235 // Make sure that we don't display the DST name by constructing a fake |
| 1236 // PST zone that has DST all year long. |
| 1237 SimpleTimeZone *zone2 = new SimpleTimeZone(0, "PST"); |
| 1238 |
| 1239 zone2->setStartRule(UCAL_JANUARY, 1, 0, 0, status); |
| 1240 zone2->setEndRule(UCAL_DECEMBER, 31, 0, 0, status); |
| 1241 |
| 1242 UnicodeString inDaylight; |
| 1243 if (zone2->inDaylightTime(UDate(0), status)) { |
| 1244 inDaylight = UnicodeString("TRUE"); |
| 1245 } else { |
| 1246 inDaylight = UnicodeString("FALSE"); |
| 1247 } |
| 1248 logln(UnicodeString("Modified PST inDaylightTime->") + inDaylight ); |
| 1249 if(U_FAILURE(status)) |
| 1250 { |
| 1251 dataerrln("Some sort of error..." + UnicodeString(u_errorName(status)));
// REVISIT |
| 1252 } |
| 1253 name.remove(); |
| 1254 name = zone2->getDisplayName(Locale::getEnglish(),name); |
| 1255 logln("Modified PST->" + name); |
| 1256 if (name.compare("Pacific Standard Time") != 0) |
| 1257 dataerrln("Fail: Expected \"Pacific Standard Time\""); |
| 1258 |
| 1259 // Make sure we get the default display format for Locales |
| 1260 // with no display name data. |
| 1261 Locale mt_MT("mt_MT"); |
| 1262 name.remove(); |
| 1263 name = zone->getDisplayName(mt_MT,name); |
| 1264 //***************************************************************** |
| 1265 // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES |
| 1266 // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES |
| 1267 // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES |
| 1268 //***************************************************************** |
| 1269 logln("PST(mt_MT)->" + name); |
| 1270 |
| 1271 // *** REVISIT SRL how in the world do I check this? looks java specific. |
| 1272 // Now be smart -- check to see if zh resource is even present. |
| 1273 // If not, we expect the en fallback behavior. |
| 1274 ResourceBundle enRB(NULL, |
| 1275 Locale::getEnglish(), status); |
| 1276 if(U_FAILURE(status)) |
| 1277 dataerrln("Couldn't get ResourceBundle for en - %s", u_errorName(status)
); |
| 1278 |
| 1279 ResourceBundle mtRB(NULL, |
| 1280 mt_MT, status); |
| 1281 //if(U_FAILURE(status)) |
| 1282 // errln("Couldn't get ResourceBundle for mt_MT"); |
| 1283 |
| 1284 UBool noZH = U_FAILURE(status); |
| 1285 |
| 1286 if (noZH) { |
| 1287 logln("Warning: Not testing the mt_MT behavior because resource is absen
t"); |
| 1288 if (name != "Pacific Standard Time") |
| 1289 dataerrln("Fail: Expected Pacific Standard Time"); |
| 1290 } |
| 1291 |
| 1292 |
| 1293 if (name.compare("GMT-08:00") && |
| 1294 name.compare("GMT-8:00") && |
| 1295 name.compare("GMT-0800") && |
| 1296 name.compare("GMT-800")) { |
| 1297 dataerrln(UnicodeString("Fail: Expected GMT-08:00 or something similar for
PST in mt_MT but got ") + name ); |
| 1298 dataerrln("************************************************************"
); |
| 1299 dataerrln("THE ABOVE FAILURE MAY JUST MEAN THE LOCALE DATA HAS CHANGED")
; |
| 1300 dataerrln("************************************************************"
); |
| 1301 } |
| 1302 |
| 1303 // Now try a non-existent zone |
| 1304 delete zone2; |
| 1305 zone2 = new SimpleTimeZone(90*60*1000, "xyzzy"); |
| 1306 name.remove(); |
| 1307 name = zone2->getDisplayName(Locale::getEnglish(),name); |
| 1308 logln("GMT+90min->" + name); |
| 1309 if (name.compare("GMT+01:30") && |
| 1310 name.compare("GMT+1:30") && |
| 1311 name.compare("GMT+0130") && |
| 1312 name.compare("GMT+130")) |
| 1313 dataerrln("Fail: Expected GMT+01:30 or something similar"); |
| 1314 name.truncate(0); |
| 1315 zone2->getDisplayName(name); |
| 1316 logln("GMT+90min->" + name); |
| 1317 if (name.compare("GMT+01:30") && |
| 1318 name.compare("GMT+1:30") && |
| 1319 name.compare("GMT+0130") && |
| 1320 name.compare("GMT+130")) |
| 1321 dataerrln("Fail: Expected GMT+01:30 or something similar"); |
| 1322 // clean up |
| 1323 delete zone; |
| 1324 delete zone2; |
| 1325 } |
| 1326 |
| 1327 /** |
| 1328 * @bug 4107276 |
| 1329 */ |
| 1330 void |
| 1331 TimeZoneTest::TestDSTSavings() |
| 1332 { |
| 1333 UErrorCode status = U_ZERO_ERROR; |
| 1334 // It might be better to find a way to integrate this test into the main Tim
eZone |
| 1335 // tests above, but I don't have time to figure out how to do this (or if it
's |
| 1336 // even really a good idea). Let's consider that a future. --rtg 1/27/98 |
| 1337 SimpleTimeZone *tz = new SimpleTimeZone(-5 * U_MILLIS_PER_HOUR, "dstSavingsT
est", |
| 1338 UCAL_MARCH, 1, 0, 0, UCAL_SEPTEMBER,
1, 0, 0, |
| 1339 (int32_t)(0.5 * U_MILLIS_PER_HOUR), s
tatus); |
| 1340 if(U_FAILURE(status)) |
| 1341 errln("couldn't create TimeZone"); |
| 1342 |
| 1343 if (tz->getRawOffset() != -5 * U_MILLIS_PER_HOUR) |
| 1344 errln(UnicodeString("Got back a raw offset of ") + (tz->getRawOffset() /
U_MILLIS_PER_HOUR) + |
| 1345 " hours instead of -5 hours."); |
| 1346 if (!tz->useDaylightTime()) |
| 1347 errln("Test time zone should use DST but claims it doesn't."); |
| 1348 if (tz->getDSTSavings() != 0.5 * U_MILLIS_PER_HOUR) |
| 1349 errln(UnicodeString("Set DST offset to 0.5 hour, but got back ") + (tz->
getDSTSavings() / |
| 1350 U_MILLIS_PER_HOUR)
+ " hours instead."); |
| 1351 |
| 1352 int32_t offset = tz->getOffset(GregorianCalendar::AD, 1998, UCAL_JANUARY, 1, |
| 1353 UCAL_THURSDAY, 10 * U_MILLIS_PER_HOUR,status); |
| 1354 if (offset != -5 * U_MILLIS_PER_HOUR) |
| 1355 errln(UnicodeString("The offset for 10 AM, 1/1/98 should have been -5 ho
urs, but we got ") |
| 1356 + (offset / U_MILLIS_PER_HOUR) + " hours."); |
| 1357 |
| 1358 offset = tz->getOffset(GregorianCalendar::AD, 1998, UCAL_JUNE, 1, UCAL_MONDA
Y, |
| 1359 10 * U_MILLIS_PER_HOUR,status); |
| 1360 if (offset != -4.5 * U_MILLIS_PER_HOUR) |
| 1361 errln(UnicodeString("The offset for 10 AM, 6/1/98 should have been -4.5
hours, but we got ") |
| 1362 + (offset / U_MILLIS_PER_HOUR) + " hours."); |
| 1363 |
| 1364 tz->setDSTSavings(U_MILLIS_PER_HOUR, status); |
| 1365 offset = tz->getOffset(GregorianCalendar::AD, 1998, UCAL_JANUARY, 1, |
| 1366 UCAL_THURSDAY, 10 * U_MILLIS_PER_HOUR,status); |
| 1367 if (offset != -5 * U_MILLIS_PER_HOUR) |
| 1368 errln(UnicodeString("The offset for 10 AM, 1/1/98 should have been -5 ho
urs, but we got ") |
| 1369 + (offset / U_MILLIS_PER_HOUR) + " hours."); |
| 1370 |
| 1371 offset = tz->getOffset(GregorianCalendar::AD, 1998, UCAL_JUNE, 1, UCAL_MONDA
Y, |
| 1372 10 * U_MILLIS_PER_HOUR,status); |
| 1373 if (offset != -4 * U_MILLIS_PER_HOUR) |
| 1374 errln(UnicodeString("The offset for 10 AM, 6/1/98 (with a 1-hour DST off
set) should have been -4 hours, but we got ") |
| 1375 + (offset / U_MILLIS_PER_HOUR) + " hours."); |
| 1376 |
| 1377 delete tz; |
| 1378 } |
| 1379 |
| 1380 /** |
| 1381 * @bug 4107570 |
| 1382 */ |
| 1383 void |
| 1384 TimeZoneTest::TestAlternateRules() |
| 1385 { |
| 1386 // Like TestDSTSavings, this test should probably be integrated somehow with
the main |
| 1387 // test at the top of this class, but I didn't have time to figure out how t
o do that. |
| 1388 // --rtg 1/28/98 |
| 1389 |
| 1390 SimpleTimeZone tz(-5 * U_MILLIS_PER_HOUR, "alternateRuleTest"); |
| 1391 |
| 1392 // test the day-of-month API |
| 1393 UErrorCode status = U_ZERO_ERROR; |
| 1394 tz.setStartRule(UCAL_MARCH, 10, 12 * U_MILLIS_PER_HOUR, status); |
| 1395 if(U_FAILURE(status)) |
| 1396 errln("tz.setStartRule failed"); |
| 1397 tz.setEndRule(UCAL_OCTOBER, 20, 12 * U_MILLIS_PER_HOUR, status); |
| 1398 if(U_FAILURE(status)) |
| 1399 errln("tz.setStartRule failed"); |
| 1400 |
| 1401 int32_t offset = tz.getOffset(GregorianCalendar::AD, 1998, UCAL_MARCH, 5, |
| 1402 UCAL_THURSDAY, 10 * U_MILLIS_PER_HOUR,status); |
| 1403 if (offset != -5 * U_MILLIS_PER_HOUR) |
| 1404 errln(UnicodeString("The offset for 10AM, 3/5/98 should have been -5 hou
rs, but we got ") |
| 1405 + (offset / U_MILLIS_PER_HOUR) + " hours."); |
| 1406 |
| 1407 offset = tz.getOffset(GregorianCalendar::AD, 1998, UCAL_MARCH, 15, |
| 1408 UCAL_SUNDAY, 10 * millisPerHour,status); |
| 1409 if (offset != -4 * U_MILLIS_PER_HOUR) |
| 1410 errln(UnicodeString("The offset for 10AM, 3/15/98 should have been -4 ho
urs, but we got ") |
| 1411 + (offset / U_MILLIS_PER_HOUR) + " hours."); |
| 1412 |
| 1413 offset = tz.getOffset(GregorianCalendar::AD, 1998, UCAL_OCTOBER, 15, |
| 1414 UCAL_THURSDAY, 10 * millisPerHour,status); |
| 1415 if (offset != -4 * U_MILLIS_PER_HOUR) |
| 1416 errln(UnicodeString("The offset for 10AM, 10/15/98 should have been -4 h
ours, but we got ") + (offset / U_MILLIS_PER_HOUR) + " hours."); |
| 1417 |
| 1418 offset = tz.getOffset(GregorianCalendar::AD, 1998, UCAL_OCTOBER, 25, |
| 1419 UCAL_SUNDAY, 10 * millisPerHour,status); |
| 1420 if (offset != -5 * U_MILLIS_PER_HOUR) |
| 1421 errln(UnicodeString("The offset for 10AM, 10/25/98 should have been -5 h
ours, but we got ") |
| 1422 + (offset / U_MILLIS_PER_HOUR) + " hours."); |
| 1423 |
| 1424 // test the day-of-week-after-day-in-month API |
| 1425 tz.setStartRule(UCAL_MARCH, 10, UCAL_FRIDAY, 12 * millisPerHour, TRUE, statu
s); |
| 1426 if(U_FAILURE(status)) |
| 1427 errln("tz.setStartRule failed"); |
| 1428 tz.setEndRule(UCAL_OCTOBER, 20, UCAL_FRIDAY, 12 * millisPerHour, FALSE, stat
us); |
| 1429 if(U_FAILURE(status)) |
| 1430 errln("tz.setStartRule failed"); |
| 1431 |
| 1432 offset = tz.getOffset(GregorianCalendar::AD, 1998, UCAL_MARCH, 11, |
| 1433 UCAL_WEDNESDAY, 10 * millisPerHour,status); |
| 1434 if (offset != -5 * U_MILLIS_PER_HOUR) |
| 1435 errln(UnicodeString("The offset for 10AM, 3/11/98 should have been -5 ho
urs, but we got ") |
| 1436 + (offset / U_MILLIS_PER_HOUR) + " hours."); |
| 1437 |
| 1438 offset = tz.getOffset(GregorianCalendar::AD, 1998, UCAL_MARCH, 14, |
| 1439 UCAL_SATURDAY, 10 * millisPerHour,status); |
| 1440 if (offset != -4 * U_MILLIS_PER_HOUR) |
| 1441 errln(UnicodeString("The offset for 10AM, 3/14/98 should have been -4 ho
urs, but we got ") |
| 1442 + (offset / U_MILLIS_PER_HOUR) + " hours."); |
| 1443 |
| 1444 offset = tz.getOffset(GregorianCalendar::AD, 1998, UCAL_OCTOBER, 15, |
| 1445 UCAL_THURSDAY, 10 * millisPerHour,status); |
| 1446 if (offset != -4 * U_MILLIS_PER_HOUR) |
| 1447 errln(UnicodeString("The offset for 10AM, 10/15/98 should have been -4 h
ours, but we got ") |
| 1448 + (offset / U_MILLIS_PER_HOUR) + " hours."); |
| 1449 |
| 1450 offset = tz.getOffset(GregorianCalendar::AD, 1998, UCAL_OCTOBER, 17, |
| 1451 UCAL_SATURDAY, 10 * millisPerHour,status); |
| 1452 if (offset != -5 * U_MILLIS_PER_HOUR) |
| 1453 errln(UnicodeString("The offset for 10AM, 10/17/98 should have been -5 h
ours, but we got ") |
| 1454 + (offset / U_MILLIS_PER_HOUR) + " hours."); |
| 1455 } |
| 1456 |
| 1457 void TimeZoneTest::TestFractionalDST() { |
| 1458 const char* tzName = "Australia/Lord_Howe"; // 30 min offset |
| 1459 TimeZone* tz_icu = TimeZone::createTimeZone(tzName); |
| 1460 int dst_icu = tz_icu->getDSTSavings(); |
| 1461 UnicodeString id; |
| 1462 int32_t expected = 1800000; |
| 1463 if (expected != dst_icu) { |
| 1464 dataerrln(UnicodeString("java reports dst savings of ") + expected + |
| 1465 " but icu reports " + dst_icu + |
| 1466 " for tz " + tz_icu->getID(id)); |
| 1467 } else { |
| 1468 logln(UnicodeString("both java and icu report dst savings of ") + ex
pected + " for tz " + tz_icu->getID(id)); |
| 1469 } |
| 1470 delete tz_icu; |
| 1471 } |
| 1472 |
| 1473 /** |
| 1474 * Test country code support. Jitterbug 776. |
| 1475 */ |
| 1476 void TimeZoneTest::TestCountries() { |
| 1477 // Make sure America/Los_Angeles is in the "US" group, and |
| 1478 // Asia/Tokyo isn't. Vice versa for the "JP" group. |
| 1479 UErrorCode ec = U_ZERO_ERROR; |
| 1480 int32_t n; |
| 1481 StringEnumeration* s = TimeZone::createEnumeration("US"); |
| 1482 n = s->count(ec); |
| 1483 UBool la = FALSE, tokyo = FALSE; |
| 1484 UnicodeString laZone("America/Los_Angeles", ""); |
| 1485 UnicodeString tokyoZone("Asia/Tokyo", ""); |
| 1486 int32_t i; |
| 1487 |
| 1488 if (s == NULL || n <= 0) { |
| 1489 dataerrln("FAIL: TimeZone::createEnumeration() returned nothing"); |
| 1490 return; |
| 1491 } |
| 1492 for (i=0; i<n; ++i) { |
| 1493 const UnicodeString* id = s->snext(ec); |
| 1494 if (*id == (laZone)) { |
| 1495 la = TRUE; |
| 1496 } |
| 1497 if (*id == (tokyoZone)) { |
| 1498 tokyo = TRUE; |
| 1499 } |
| 1500 } |
| 1501 if (!la || tokyo) { |
| 1502 errln("FAIL: " + laZone + " in US = " + la); |
| 1503 errln("FAIL: " + tokyoZone + " in US = " + tokyo); |
| 1504 } |
| 1505 delete s; |
| 1506 |
| 1507 s = TimeZone::createEnumeration("JP"); |
| 1508 n = s->count(ec); |
| 1509 la = FALSE; tokyo = FALSE; |
| 1510 |
| 1511 for (i=0; i<n; ++i) { |
| 1512 const UnicodeString* id = s->snext(ec); |
| 1513 if (*id == (laZone)) { |
| 1514 la = TRUE; |
| 1515 } |
| 1516 if (*id == (tokyoZone)) { |
| 1517 tokyo = TRUE; |
| 1518 } |
| 1519 } |
| 1520 if (la || !tokyo) { |
| 1521 errln("FAIL: " + laZone + " in JP = " + la); |
| 1522 errln("FAIL: " + tokyoZone + " in JP = " + tokyo); |
| 1523 } |
| 1524 StringEnumeration* s1 = TimeZone::createEnumeration("US"); |
| 1525 StringEnumeration* s2 = TimeZone::createEnumeration("US"); |
| 1526 for(i=0;i<n;++i){ |
| 1527 const UnicodeString* id1 = s1->snext(ec); |
| 1528 if(id1==NULL || U_FAILURE(ec)){ |
| 1529 errln("Failed to fetch next from TimeZone enumeration. Length return
ed : %i Current Index: %i", n,i); |
| 1530 } |
| 1531 TimeZone* tz1 = TimeZone::createTimeZone(*id1); |
| 1532 for(int j=0; j<n;++j){ |
| 1533 const UnicodeString* id2 = s2->snext(ec); |
| 1534 if(id2==NULL || U_FAILURE(ec)){ |
| 1535 errln("Failed to fetch next from TimeZone enumeration. Length re
turned : %i Current Index: %i", n,i); |
| 1536 } |
| 1537 TimeZone* tz2 = TimeZone::createTimeZone(*id2); |
| 1538 if(tz1->hasSameRules(*tz2)){ |
| 1539 logln("ID1 : " + *id1+" == ID2 : " +*id2); |
| 1540 } |
| 1541 delete tz2; |
| 1542 } |
| 1543 delete tz1; |
| 1544 } |
| 1545 delete s1; |
| 1546 delete s2; |
| 1547 delete s; |
| 1548 } |
| 1549 |
| 1550 void TimeZoneTest::TestHistorical() { |
| 1551 const int32_t H = U_MILLIS_PER_HOUR; |
| 1552 struct { |
| 1553 const char* id; |
| 1554 int32_t time; // epoch seconds |
| 1555 int32_t offset; // total offset (millis) |
| 1556 } DATA[] = { |
| 1557 // Add transition points (before/after) as desired to test historical |
| 1558 // behavior. |
| 1559 {"America/Los_Angeles", 638963999, -8*H}, // Sun Apr 01 01:59:59 GMT-08:
00 1990 |
| 1560 {"America/Los_Angeles", 638964000, -7*H}, // Sun Apr 01 03:00:00 GMT-07:
00 1990 |
| 1561 {"America/Los_Angeles", 657104399, -7*H}, // Sun Oct 28 01:59:59 GMT-07:
00 1990 |
| 1562 {"America/Los_Angeles", 657104400, -8*H}, // Sun Oct 28 01:00:00 GMT-08:
00 1990 |
| 1563 {"America/Goose_Bay", -116445601, -4*H}, // Sun Apr 24 01:59:59 GMT-04:0
0 1966 |
| 1564 {"America/Goose_Bay", -116445600, -3*H}, // Sun Apr 24 03:00:00 GMT-03:0
0 1966 |
| 1565 {"America/Goose_Bay", -100119601, -3*H}, // Sun Oct 30 01:59:59 GMT-03:0
0 1966 |
| 1566 {"America/Goose_Bay", -100119600, -4*H}, // Sun Oct 30 01:00:00 GMT-04:0
0 1966 |
| 1567 {"America/Goose_Bay", -84391201, -4*H}, // Sun Apr 30 01:59:59 GMT-04:00
1967 |
| 1568 {"America/Goose_Bay", -84391200, -3*H}, // Sun Apr 30 03:00:00 GMT-03:00
1967 |
| 1569 {"America/Goose_Bay", -68670001, -3*H}, // Sun Oct 29 01:59:59 GMT-03:00
1967 |
| 1570 {"America/Goose_Bay", -68670000, -4*H}, // Sun Oct 29 01:00:00 GMT-04:00
1967 |
| 1571 {0, 0, 0} |
| 1572 }; |
| 1573 |
| 1574 for (int32_t i=0; DATA[i].id!=0; ++i) { |
| 1575 const char* id = DATA[i].id; |
| 1576 TimeZone *tz = TimeZone::createTimeZone(id); |
| 1577 UnicodeString s; |
| 1578 if (tz == 0) { |
| 1579 errln("FAIL: Cannot create %s", id); |
| 1580 } else if (tz->getID(s) != UnicodeString(id)) { |
| 1581 dataerrln((UnicodeString)"FAIL: createTimeZone(" + id + ") => " + s)
; |
| 1582 } else { |
| 1583 UErrorCode ec = U_ZERO_ERROR; |
| 1584 int32_t raw, dst; |
| 1585 UDate when = (double) DATA[i].time * U_MILLIS_PER_SECOND; |
| 1586 tz->getOffset(when, FALSE, raw, dst, ec); |
| 1587 if (U_FAILURE(ec)) { |
| 1588 errln("FAIL: getOffset"); |
| 1589 } else if ((raw+dst) != DATA[i].offset) { |
| 1590 errln((UnicodeString)"FAIL: " + DATA[i].id + ".getOffset(" + |
| 1591 //when + " = " + |
| 1592 dateToString(when) + ") => " + |
| 1593 raw + ", " + dst); |
| 1594 } else { |
| 1595 logln((UnicodeString)"Ok: " + DATA[i].id + ".getOffset(" + |
| 1596 //when + " = " + |
| 1597 dateToString(when) + ") => " + |
| 1598 raw + ", " + dst); |
| 1599 } |
| 1600 } |
| 1601 delete tz; |
| 1602 } |
| 1603 } |
| 1604 |
| 1605 void TimeZoneTest::TestEquivalentIDs() { |
| 1606 int32_t n = TimeZone::countEquivalentIDs("PST"); |
| 1607 if (n < 2) { |
| 1608 dataerrln((UnicodeString)"FAIL: countEquivalentIDs(PST) = " + n); |
| 1609 } else { |
| 1610 UBool sawLA = FALSE; |
| 1611 for (int32_t i=0; i<n; ++i) { |
| 1612 UnicodeString id = TimeZone::getEquivalentID("PST", i); |
| 1613 logln((UnicodeString)"" + i + " : " + id); |
| 1614 if (id == UnicodeString("America/Los_Angeles")) { |
| 1615 sawLA = TRUE; |
| 1616 } |
| 1617 } |
| 1618 if (!sawLA) { |
| 1619 errln("FAIL: America/Los_Angeles should be in the list"); |
| 1620 } |
| 1621 } |
| 1622 } |
| 1623 |
| 1624 // Test that a transition at the end of February is handled correctly. |
| 1625 void TimeZoneTest::TestFebruary() { |
| 1626 UErrorCode status = U_ZERO_ERROR; |
| 1627 |
| 1628 // Time zone with daylight savings time from the first Sunday in November |
| 1629 // to the last Sunday in February. |
| 1630 // Similar to the new rule for Brazil (Sao Paulo) in tzdata2006n. |
| 1631 // |
| 1632 // Note: In tzdata2007h, the rule had changed, so no actual zones uses |
| 1633 // lastSun in Feb anymore. |
| 1634 SimpleTimeZone tz1(-3 * U_MILLIS_PER_HOUR, // raw offset: 3h before
(west of) GMT |
| 1635 UNICODE_STRING("nov-feb", 7), |
| 1636 UCAL_NOVEMBER, 1, UCAL_SUNDAY, // start: November, firs
t, Sunday |
| 1637 0, // midnight wall
time |
| 1638 UCAL_FEBRUARY, -1, UCAL_SUNDAY, // end: February, last
, Sunday |
| 1639 0, // midnight wall
time |
| 1640 status); |
| 1641 if (U_FAILURE(status)) { |
| 1642 errln("Unable to create the SimpleTimeZone(nov-feb): %s", u_errorName(st
atus)); |
| 1643 return; |
| 1644 } |
| 1645 |
| 1646 // Now hardcode the same rules as for Brazil in tzdata 2006n, so that |
| 1647 // we cover the intended code even when in the future zoneinfo hardcodes |
| 1648 // these transition dates. |
| 1649 SimpleTimeZone tz2(-3 * U_MILLIS_PER_HOUR, // raw offset: 3h before
(west of) GMT |
| 1650 UNICODE_STRING("nov-feb2", 8), |
| 1651 UCAL_NOVEMBER, 1, -UCAL_SUNDAY, // start: November, 1 or
after, Sunday |
| 1652 0, // midnight wall
time |
| 1653 UCAL_FEBRUARY, -29, -UCAL_SUNDAY,// end: February, 29 o
r before, Sunday |
| 1654 0, // midnight wall
time |
| 1655 status); |
| 1656 if (U_FAILURE(status)) { |
| 1657 errln("Unable to create the SimpleTimeZone(nov-feb2): %s", u_errorName(s
tatus)); |
| 1658 return; |
| 1659 } |
| 1660 |
| 1661 // Gregorian calendar with the UTC time zone for getting sample test date/ti
mes. |
| 1662 GregorianCalendar gc(*TimeZone::getGMT(), status); |
| 1663 if (U_FAILURE(status)) { |
| 1664 dataerrln("Unable to create the UTC calendar: %s", u_errorName(status)); |
| 1665 return; |
| 1666 } |
| 1667 |
| 1668 struct { |
| 1669 // UTC time. |
| 1670 int32_t year, month, day, hour, minute, second; |
| 1671 // Expected time zone offset in hours after GMT (negative=before GMT). |
| 1672 int32_t offsetHours; |
| 1673 } data[] = { |
| 1674 { 2006, UCAL_NOVEMBER, 5, 02, 59, 59, -3 }, |
| 1675 { 2006, UCAL_NOVEMBER, 5, 03, 00, 00, -2 }, |
| 1676 { 2007, UCAL_FEBRUARY, 25, 01, 59, 59, -2 }, |
| 1677 { 2007, UCAL_FEBRUARY, 25, 02, 00, 00, -3 }, |
| 1678 |
| 1679 { 2007, UCAL_NOVEMBER, 4, 02, 59, 59, -3 }, |
| 1680 { 2007, UCAL_NOVEMBER, 4, 03, 00, 00, -2 }, |
| 1681 { 2008, UCAL_FEBRUARY, 24, 01, 59, 59, -2 }, |
| 1682 { 2008, UCAL_FEBRUARY, 24, 02, 00, 00, -3 }, |
| 1683 |
| 1684 { 2008, UCAL_NOVEMBER, 2, 02, 59, 59, -3 }, |
| 1685 { 2008, UCAL_NOVEMBER, 2, 03, 00, 00, -2 }, |
| 1686 { 2009, UCAL_FEBRUARY, 22, 01, 59, 59, -2 }, |
| 1687 { 2009, UCAL_FEBRUARY, 22, 02, 00, 00, -3 }, |
| 1688 |
| 1689 { 2009, UCAL_NOVEMBER, 1, 02, 59, 59, -3 }, |
| 1690 { 2009, UCAL_NOVEMBER, 1, 03, 00, 00, -2 }, |
| 1691 { 2010, UCAL_FEBRUARY, 28, 01, 59, 59, -2 }, |
| 1692 { 2010, UCAL_FEBRUARY, 28, 02, 00, 00, -3 } |
| 1693 }; |
| 1694 |
| 1695 TimeZone *timezones[] = { &tz1, &tz2 }; |
| 1696 |
| 1697 TimeZone *tz; |
| 1698 UDate dt; |
| 1699 int32_t t, i, raw, dst; |
| 1700 for (t = 0; t < LENGTHOF(timezones); ++t) { |
| 1701 tz = timezones[t]; |
| 1702 for (i = 0; i < LENGTHOF(data); ++i) { |
| 1703 gc.set(data[i].year, data[i].month, data[i].day, |
| 1704 data[i].hour, data[i].minute, data[i].second); |
| 1705 dt = gc.getTime(status); |
| 1706 if (U_FAILURE(status)) { |
| 1707 errln("test case %d.%d: bad date/time %04d-%02d-%02d %02d:%02d:%
02d", |
| 1708 t, i, |
| 1709 data[i].year, data[i].month + 1, data[i].day, |
| 1710 data[i].hour, data[i].minute, data[i].second); |
| 1711 status = U_ZERO_ERROR; |
| 1712 continue; |
| 1713 } |
| 1714 tz->getOffset(dt, FALSE, raw, dst, status); |
| 1715 if (U_FAILURE(status)) { |
| 1716 errln("test case %d.%d: tz.getOffset(%04d-%02d-%02d %02d:%02d:%0
2d) fails: %s", |
| 1717 t, i, |
| 1718 data[i].year, data[i].month + 1, data[i].day, |
| 1719 data[i].hour, data[i].minute, data[i].second, |
| 1720 u_errorName(status)); |
| 1721 status = U_ZERO_ERROR; |
| 1722 } else if ((raw + dst) != data[i].offsetHours * U_MILLIS_PER_HOUR) { |
| 1723 errln("test case %d.%d: tz.getOffset(%04d-%02d-%02d %02d:%02d:%0
2d) returns %d+%d != %d", |
| 1724 t, i, |
| 1725 data[i].year, data[i].month + 1, data[i].day, |
| 1726 data[i].hour, data[i].minute, data[i].second, |
| 1727 raw, dst, data[i].offsetHours * U_MILLIS_PER_HOUR); |
| 1728 } |
| 1729 } |
| 1730 } |
| 1731 } |
| 1732 void TimeZoneTest::TestCanonicalID() { |
| 1733 |
| 1734 // Some canonical IDs in CLDR are defined as "Link" |
| 1735 // in Olson tzdata. |
| 1736 static const struct { |
| 1737 const char *alias; |
| 1738 const char *zone; |
| 1739 } excluded1[] = { |
| 1740 {"America/Shiprock", "America/Denver"}, // America/Shiprock is defined a
s a Link to America/Denver in tzdata |
| 1741 {"America/Marigot", "America/Guadeloupe"}, |
| 1742 {"America/St_Barthelemy", "America/Guadeloupe"}, |
| 1743 {"Antarctica/South_Pole", "Antarctica/McMurdo"}, |
| 1744 {"Atlantic/Jan_Mayen", "Europe/Oslo"}, |
| 1745 {"Arctic/Longyearbyen", "Europe/Oslo"}, |
| 1746 {"Europe/Guernsey", "Europe/London"}, |
| 1747 {"Europe/Isle_of_Man", "Europe/London"}, |
| 1748 {"Europe/Jersey", "Europe/London"}, |
| 1749 {"Europe/Ljubljana", "Europe/Belgrade"}, |
| 1750 {"Europe/Podgorica", "Europe/Belgrade"}, |
| 1751 {"Europe/Sarajevo", "Europe/Belgrade"}, |
| 1752 {"Europe/Skopje", "Europe/Belgrade"}, |
| 1753 {"Europe/Zagreb", "Europe/Belgrade"}, |
| 1754 {"Europe/Bratislava", "Europe/Prague"}, |
| 1755 {"Europe/Mariehamn", "Europe/Helsinki"}, |
| 1756 {"Europe/San_Marino", "Europe/Rome"}, |
| 1757 {"Europe/Vatican", "Europe/Rome"}, |
| 1758 {0, 0} |
| 1759 }; |
| 1760 |
| 1761 // Following IDs are aliases of Etc/GMT in CLDR, |
| 1762 // but Olson tzdata has 3 independent definitions |
| 1763 // for Etc/GMT, Etc/UTC, Etc/UCT. |
| 1764 // Until we merge them into one equivalent group |
| 1765 // in zoneinfo.res, we exclude them in the test |
| 1766 // below. |
| 1767 static const char* excluded2[] = { |
| 1768 "Etc/UCT", "UCT", |
| 1769 "Etc/UTC", "UTC", |
| 1770 "Etc/Universal", "Universal", |
| 1771 "Etc/Zulu", "Zulu", 0 |
| 1772 }; |
| 1773 |
| 1774 // Walk through equivalency groups |
| 1775 UErrorCode ec = U_ZERO_ERROR; |
| 1776 int32_t s_length, i, j, k; |
| 1777 StringEnumeration* s = TimeZone::createEnumeration(); |
| 1778 UnicodeString canonicalID, tmpCanonical; |
| 1779 s_length = s->count(ec); |
| 1780 for (i = 0; i < s_length;++i) { |
| 1781 const UnicodeString *tzid = s->snext(ec); |
| 1782 int32_t nEquiv = TimeZone::countEquivalentIDs(*tzid); |
| 1783 if (nEquiv == 0) { |
| 1784 continue; |
| 1785 } |
| 1786 UBool bFoundCanonical = FALSE; |
| 1787 // Make sure getCanonicalID returns the exact same result |
| 1788 // for all entries within a same equivalency group with some |
| 1789 // exceptions listed in exluded1. |
| 1790 // Also, one of them must be canonical id. |
| 1791 for (j = 0; j < nEquiv; j++) { |
| 1792 UnicodeString tmp = TimeZone::getEquivalentID(*tzid, j); |
| 1793 TimeZone::getCanonicalID(tmp, tmpCanonical, ec); |
| 1794 if (U_FAILURE(ec)) { |
| 1795 errln((UnicodeString)"FAIL: getCanonicalID(" + tmp + ") failed."
); |
| 1796 ec = U_ZERO_ERROR; |
| 1797 continue; |
| 1798 } |
| 1799 // Some exceptional cases |
| 1800 for (k = 0; excluded1[k].alias != 0; k++) { |
| 1801 if (tmpCanonical == excluded1[k].alias) { |
| 1802 tmpCanonical = excluded1[k].zone; |
| 1803 break; |
| 1804 } |
| 1805 } |
| 1806 if (j == 0) { |
| 1807 canonicalID = tmpCanonical; |
| 1808 } else if (canonicalID != tmpCanonical) { |
| 1809 errln("FAIL: getCanonicalID(" + tmp + ") returned " + tmpCanonic
al + " expected:" + canonicalID); |
| 1810 } |
| 1811 |
| 1812 if (canonicalID == tmp) { |
| 1813 bFoundCanonical = TRUE; |
| 1814 } |
| 1815 } |
| 1816 // At least one ID in an equvalency group must match the |
| 1817 // canonicalID |
| 1818 if (bFoundCanonical == FALSE) { |
| 1819 // test exclusion because of differences between Olson tzdata and CL
DR |
| 1820 UBool isExcluded = FALSE; |
| 1821 for (k = 0; excluded2[k] != 0; k++) { |
| 1822 if (*tzid == UnicodeString(excluded2[k])) { |
| 1823 isExcluded = TRUE; |
| 1824 break; |
| 1825 } |
| 1826 } |
| 1827 if (isExcluded) { |
| 1828 continue; |
| 1829 } |
| 1830 errln((UnicodeString)"FAIL: No timezone ids match the canonical ID "
+ canonicalID); |
| 1831 } |
| 1832 } |
| 1833 delete s; |
| 1834 |
| 1835 // Testing some special cases |
| 1836 static const struct { |
| 1837 const char *id; |
| 1838 const char *expected; |
| 1839 UBool isSystem; |
| 1840 } data[] = { |
| 1841 {"GMT-03", "GMT-03:00", FALSE}, |
| 1842 {"GMT+4", "GMT+04:00", FALSE}, |
| 1843 {"GMT-055", "GMT-00:55", FALSE}, |
| 1844 {"GMT+430", "GMT+04:30", FALSE}, |
| 1845 {"GMT-12:15", "GMT-12:15", FALSE}, |
| 1846 {"GMT-091015", "GMT-09:10:15", FALSE}, |
| 1847 {"GMT+1:90", 0, FALSE}, |
| 1848 {"America/Argentina/Buenos_Aires", "America/Buenos_Aires", TRUE}, |
| 1849 {"bogus", 0, FALSE}, |
| 1850 {"", 0, FALSE}, |
| 1851 {0, 0, FALSE} |
| 1852 }; |
| 1853 |
| 1854 UBool isSystemID; |
| 1855 for (i = 0; data[i].id != 0; i++) { |
| 1856 TimeZone::getCanonicalID(UnicodeString(data[i].id), canonicalID, isSyste
mID, ec); |
| 1857 if (U_FAILURE(ec)) { |
| 1858 if (ec != U_ILLEGAL_ARGUMENT_ERROR || data[i].expected != 0) { |
| 1859 errln((UnicodeString)"FAIL: getCanonicalID(\"" + data[i].id |
| 1860 + "\") returned status U_ILLEGAL_ARGUMENT_ERROR"); |
| 1861 } |
| 1862 ec = U_ZERO_ERROR; |
| 1863 continue; |
| 1864 } |
| 1865 if (canonicalID != data[i].expected) { |
| 1866 dataerrln((UnicodeString)"FAIL: getCanonicalID(\"" + data[i].id |
| 1867 + "\") returned " + canonicalID + " - expected: " + data[i].expe
cted); |
| 1868 } |
| 1869 if (isSystemID != data[i].isSystem) { |
| 1870 dataerrln((UnicodeString)"FAIL: getCanonicalID(\"" + data[i].id |
| 1871 + "\") set " + isSystemID + " to isSystemID"); |
| 1872 } |
| 1873 } |
| 1874 } |
| 1875 |
| 1876 // |
| 1877 // Test Display Names, choosing zones and lcoales where there are multiple |
| 1878 // meta-zones defined. |
| 1879 // |
| 1880 static struct { |
| 1881 const char *zoneName; |
| 1882 const char *localeName; |
| 1883 UBool summerTime; |
| 1884 TimeZone::EDisplayType style; |
| 1885 const char *expectedDisplayName; } |
| 1886 zoneDisplayTestData [] = { |
| 1887 // zone id locale summer format expected display name |
| 1888 {"Europe/London", "en", FALSE, TimeZone::SHORT, "GMT"}, |
| 1889 {"Europe/London", "en", FALSE, TimeZone::LONG, "Greenwich Mean Time"}
, |
| 1890 {"Europe/London", "en", TRUE, TimeZone::SHORT, "GMT+01:00" /*"BST"*/}
, |
| 1891 {"Europe/London", "en", TRUE, TimeZone::LONG, "British Summer Time"}
, |
| 1892 |
| 1893 {"America/Anchorage", "en", FALSE, TimeZone::SHORT, "AKST"}, |
| 1894 {"America/Anchorage", "en", FALSE, TimeZone::LONG, "Alaska Standard Time"
}, |
| 1895 {"America/Anchorage", "en", TRUE, TimeZone::SHORT, "AKDT"}, |
| 1896 {"America/Anchorage", "en", TRUE, TimeZone::LONG, "Alaska Daylight Time"
}, |
| 1897 |
| 1898 // Southern Hemisphere, all data from meta:Australia_Western |
| 1899 {"Australia/Perth", "en", FALSE, TimeZone::SHORT, "GMT+08:00"/*"AWST"*/}
, |
| 1900 {"Australia/Perth", "en", FALSE, TimeZone::LONG, "Australian Western St
andard Time"}, |
| 1901 {"Australia/Perth", "en", TRUE, TimeZone::SHORT, "GMT+09:00"/*"AWDT"*/}
, |
| 1902 {"Australia/Perth", "en", TRUE, TimeZone::LONG, "Australian Western Da
ylight Time"}, |
| 1903 |
| 1904 {"America/Sao_Paulo", "en", FALSE, TimeZone::SHORT, "GMT-03:00"/*"BRT"*/}
, |
| 1905 {"America/Sao_Paulo", "en", FALSE, TimeZone::LONG, "Brasilia Time"}, |
| 1906 {"America/Sao_Paulo", "en", TRUE, TimeZone::SHORT, "GMT-02:00"/*"BRST"*/
}, |
| 1907 {"America/Sao_Paulo", "en", TRUE, TimeZone::LONG, "Brasilia Summer Time
"}, |
| 1908 |
| 1909 // No Summer Time, but had it before 1983. |
| 1910 {"Pacific/Honolulu", "en", FALSE, TimeZone::SHORT, "HST"}, |
| 1911 {"Pacific/Honolulu", "en", FALSE, TimeZone::LONG, "Hawaii-Aleutian Stan
dard Time"}, |
| 1912 {"Pacific/Honolulu", "en", TRUE, TimeZone::SHORT, "HST"}, |
| 1913 {"Pacific/Honolulu", "en", TRUE, TimeZone::LONG, "Hawaii-Aleutian Stan
dard Time"}, |
| 1914 |
| 1915 // Northern, has Summer, not commonly used. |
| 1916 {"Europe/Helsinki", "en", FALSE, TimeZone::SHORT, "GMT+02:00"/*"EET"*/}
, |
| 1917 {"Europe/Helsinki", "en", FALSE, TimeZone::LONG, "Eastern European Tim
e"}, |
| 1918 {"Europe/Helsinki", "en", TRUE, TimeZone::SHORT, "GMT+03:00"/*"EEST"*/
}, |
| 1919 {"Europe/Helsinki", "en", true, TimeZone::LONG, "Eastern European Sum
mer Time"}, |
| 1920 {NULL, NULL, FALSE, TimeZone::SHORT, NULL} // NULL values terminate list |
| 1921 }; |
| 1922 |
| 1923 void TimeZoneTest::TestDisplayNamesMeta() { |
| 1924 UErrorCode status = U_ZERO_ERROR; |
| 1925 GregorianCalendar cal(*TimeZone::getGMT(), status); |
| 1926 if (failure(status, "GregorianCalendar", TRUE)) return; |
| 1927 |
| 1928 UBool isReferenceYear = TRUE; |
| 1929 if (cal.get(UCAL_YEAR, status) != TimeZoneTest::REFERENCE_YEAR) { |
| 1930 isReferenceYear = FALSE; |
| 1931 } |
| 1932 |
| 1933 UBool sawAnError = FALSE; |
| 1934 for (int testNum = 0; zoneDisplayTestData[testNum].zoneName != NULL; testN
um++) { |
| 1935 Locale locale = Locale::createFromName(zoneDisplayTestData[testNum].loc
aleName); |
| 1936 TimeZone *zone = TimeZone::createTimeZone(zoneDisplayTestData[testNum].z
oneName); |
| 1937 UnicodeString displayName; |
| 1938 zone->getDisplayName(zoneDisplayTestData[testNum].summerTime, |
| 1939 zoneDisplayTestData[testNum].style, |
| 1940 locale, |
| 1941 displayName); |
| 1942 if (displayName != zoneDisplayTestData[testNum].expectedDisplayName) { |
| 1943 char name[100]; |
| 1944 UErrorCode status = U_ZERO_ERROR; |
| 1945 displayName.extract(name, 100, NULL, status); |
| 1946 if (isReferenceYear) { |
| 1947 sawAnError = TRUE; |
| 1948 dataerrln("Incorrect time zone display name. zone = \"%s\",\n" |
| 1949 " locale = \"%s\", style = %s, Summertime = %d\n" |
| 1950 " Expected \"%s\", " |
| 1951 " Got \"%s\"\n Error: %s", zoneDisplayTestData[testNum
].zoneName, |
| 1952 zoneDisplayTestData[testNum].localeName
, |
| 1953 zoneDisplayTestData[testNum].style==Tim
eZone::SHORT ? |
| 1954 "SHORT" : "LONG", |
| 1955 zoneDisplayTestData[testNum].summerTime
, |
| 1956 zoneDisplayTestData[testNum].expectedDi
splayName, |
| 1957 name, |
| 1958 u_errorName(status)); |
| 1959 } else { |
| 1960 logln("Incorrect time zone display name. zone = \"%s\",\n" |
| 1961 " locale = \"%s\", style = %s, Summertime = %d\n" |
| 1962 " Expected \"%s\", " |
| 1963 " Got \"%s\"\n", zoneDisplayTestData[testNum].zoneName, |
| 1964 zoneDisplayTestData[testNum].localeName
, |
| 1965 zoneDisplayTestData[testNum].style==Tim
eZone::SHORT ? |
| 1966 "SHORT" : "LONG", |
| 1967 zoneDisplayTestData[testNum].summerTime
, |
| 1968 zoneDisplayTestData[testNum].expectedDi
splayName, |
| 1969 name); |
| 1970 } |
| 1971 } |
| 1972 delete zone; |
| 1973 } |
| 1974 if (sawAnError) { |
| 1975 dataerrln("***Note: Errors could be the result of changes to zoneStrings
locale data"); |
| 1976 } |
| 1977 } |
| 1978 |
| 1979 #endif /* #if !UCONFIG_NO_FORMATTING */ |
OLD | NEW |