1 /******************************************************************** 2 * Copyright (c) 1997-2010, International Business Machines 3 * Corporation and others. All Rights Reserved. 4 ********************************************************************/ 5 6 #include "unicode/utypes.h" 7 8 #if !UCONFIG_NO_FORMATTING 9 10 #include "unicode/simpletz.h" 11 #include "unicode/smpdtfmt.h" 12 #include "unicode/strenum.h" 13 #include "tzregts.h" 14 #include "calregts.h" 15 #include "cmemory.h" 16 17 // ***************************************************************************** 18 // class TimeZoneRegressionTest 19 // ***************************************************************************** 20 /* length of an array */ 21 #define ARRAY_LENGTH(array) (sizeof(array)/sizeof(array[0])) 22 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break 23 24 void 25 TimeZoneRegressionTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) 26 { 27 // if (exec) logln((UnicodeString)"TestSuite NumberFormatRegressionTest"); 28 switch (index) { 29 30 CASE(0, Test4052967); 31 CASE(1, Test4073209); 32 CASE(2, Test4073215); 33 CASE(3, Test4084933); 34 CASE(4, Test4096952); 35 CASE(5, Test4109314); 36 CASE(6, Test4126678); 37 CASE(7, Test4151406); 38 CASE(8, Test4151429); 39 CASE(9, Test4154537); 40 CASE(10, Test4154542); 41 CASE(11, Test4154650); 42 CASE(12, Test4154525); 43 CASE(13, Test4162593); 44 CASE(14, TestJ186); 45 CASE(15, TestJ449); 46 CASE(16, TestJDK12API); 47 CASE(17, Test4176686); 48 CASE(18, Test4184229); 49 default: name = ""; break; 50 } 51 } 52 53 UBool 54 TimeZoneRegressionTest::failure(UErrorCode status, const char* msg) 55 { 56 if(U_FAILURE(status)) { 57 errln(UnicodeString("FAIL: ") + msg + " failed, error " + u_errorName(status)); 58 return TRUE; 59 } 60 61 return FALSE; 62 } 63 64 /** 65 * @bug 4052967 66 */ 67 void TimeZoneRegressionTest:: Test4052967() { 68 // {sfb} not applicable in C++ ? 69 /*logln("*** CHECK TIMEZONE AGAINST HOST OS SETTING ***"); 70 logln("user.timezone:" + System.getProperty("user.timezone", "<not set>")); 71 logln(new Date().toString()); 72 logln("*** THE RESULTS OF THIS TEST MUST BE VERIFIED MANUALLY ***");*/ 73 } 74 75 /** 76 * @bug 4073209 77 */ 78 void TimeZoneRegressionTest:: Test4073209() { 79 TimeZone *z1 = TimeZone::createTimeZone("PST"); 80 TimeZone *z2 = TimeZone::createTimeZone("PST"); 81 if (z1 == z2) 82 errln("Fail: TimeZone should return clones"); 83 delete z1; 84 delete z2; 85 } 86 87 UDate TimeZoneRegressionTest::findTransitionBinary(const SimpleTimeZone& tz, UDate min, UDate max) { 88 UErrorCode status = U_ZERO_ERROR; 89 UBool startsInDST = tz.inDaylightTime(min, status); 90 if (failure(status, "SimpleTimeZone::inDaylightTime")) return 0; 91 if (tz.inDaylightTime(max, status) == startsInDST) { 92 logln((UnicodeString)"Error: inDaylightTime() != " + ((!startsInDST)?"TRUE":"FALSE")); 93 return 0; 94 } 95 if (failure(status, "SimpleTimeZone::inDaylightTime")) return 0; 96 while ((max - min) > 100) { // Min accuracy in ms 97 UDate mid = (min + max) / 2; 98 if (tz.inDaylightTime(mid, status) == startsInDST) { 99 min = mid; 100 } else { 101 max = mid; 102 } 103 if (failure(status, "SimpleTimeZone::inDaylightTime")) return 0; 104 } 105 return (min + max) / 2; 106 } 107 108 UDate TimeZoneRegressionTest::findTransitionStepwise(const SimpleTimeZone& tz, UDate min, UDate max) { 109 UErrorCode status = U_ZERO_ERROR; 110 UBool startsInDST = tz.inDaylightTime(min, status); 111 if (failure(status, "SimpleTimeZone::inDaylightTime")) return 0; 112 while (min < max) { 113 if (tz.inDaylightTime(min, status) != startsInDST) { 114 return min; 115 } 116 if (failure(status, "SimpleTimeZone::inDaylightTime")) return 0; 117 min += (UDate)24*60*60*1000; // one day 118 } 119 return 0; 120 } 121 122 /** 123 * @bug 4073215 124 */ 125 // {sfb} will this work using a Calendar? 126 void TimeZoneRegressionTest:: Test4073215() 127 { 128 UErrorCode status = U_ZERO_ERROR; 129 UnicodeString str, str2; 130 SimpleTimeZone *z = new SimpleTimeZone(0, "GMT"); 131 if (z->useDaylightTime()) 132 errln("Fail: Fix test to start with non-DST zone"); 133 z->setStartRule(UCAL_FEBRUARY, 1, UCAL_SUNDAY, 0, status); 134 failure(status, "z->setStartRule()"); 135 z->setEndRule(UCAL_MARCH, -1, UCAL_SUNDAY, 0, status); 136 failure(status, "z->setStartRule()"); 137 if (!z->useDaylightTime()) 138 errln("Fail: DST not active"); 139 140 GregorianCalendar cal(1997, UCAL_JANUARY, 31, status); 141 if(U_FAILURE(status)) { 142 dataerrln("Error creating calendar %s", u_errorName(status)); 143 return; 144 } 145 failure(status, "new GregorianCalendar"); 146 cal.adoptTimeZone(z); 147 148 SimpleDateFormat sdf((UnicodeString)"E d MMM yyyy G HH:mm", status); 149 if(U_FAILURE(status)) { 150 errcheckln(status, "Error creating date format %s", u_errorName(status)); 151 return; 152 } 153 sdf.setCalendar(cal); 154 failure(status, "new SimpleDateFormat"); 155 156 UDate jan31, mar1, mar31; 157 158 UBool indt = z->inDaylightTime(jan31=cal.getTime(status), status); 159 failure(status, "inDaylightTime or getTime call on Jan 31"); 160 if (indt) { 161 errln("Fail: Jan 31 inDaylightTime=TRUE, exp FALSE"); 162 } 163 cal.set(1997, UCAL_MARCH, 1); 164 indt = z->inDaylightTime(mar1=cal.getTime(status), status); 165 failure(status, "inDaylightTime or getTime call on Mar 1"); 166 if (!indt) { 167 UnicodeString str; 168 sdf.format(cal.getTime(status), str); 169 failure(status, "getTime"); 170 errln((UnicodeString)"Fail: " + str + " inDaylightTime=FALSE, exp TRUE"); 171 } 172 cal.set(1997, UCAL_MARCH, 31); 173 indt = z->inDaylightTime(mar31=cal.getTime(status), status); 174 failure(status, "inDaylightTime or getTime call on Mar 31"); 175 if (indt) { 176 errln("Fail: Mar 31 inDaylightTime=TRUE, exp FALSE"); 177 } 178 179 /* 180 cal.set(1997, Calendar::DECEMBER, 31); 181 UDate dec31 = cal.getTime(status); 182 failure(status, "getTime"); 183 UDate trans = findTransitionStepwise(*z, jan31, dec31); 184 logln((UnicodeString)"Stepwise from " + 185 sdf.format(jan31, str.remove()) + "; transition at " + 186 (trans?sdf.format(trans, str2.remove()):(UnicodeString)"NONE")); 187 trans = findTransitionStepwise(*z, mar1, dec31); 188 logln((UnicodeString)"Stepwise from " + 189 sdf.format(mar1, str.remove()) + "; transition at " + 190 (trans?sdf.format(trans, str2.remove()):(UnicodeString)"NONE")); 191 trans = findTransitionStepwise(*z, mar31, dec31); 192 logln((UnicodeString)"Stepwise from " + 193 sdf.format(mar31, str.remove()) + "; transition at " + 194 (trans?sdf.format(trans, str2.remove()):(UnicodeString)"NONE")); 195 */ 196 } 197 198 /** 199 * @bug 4084933 200 * The expected behavior of TimeZone around the boundaries is: 201 * (Assume transition time of 2:00 AM) 202 * day of onset 1:59 AM STD = display name 1:59 AM ST 203 * 2:00 AM STD = display name 3:00 AM DT 204 * day of end 0:59 AM STD = display name 1:59 AM DT 205 * 1:00 AM STD = display name 1:00 AM ST 206 */ 207 void TimeZoneRegressionTest:: Test4084933() { 208 UErrorCode status = U_ZERO_ERROR; 209 TimeZone *tz = TimeZone::createTimeZone("PST"); 210 211 int32_t offset1 = tz->getOffset(1, 212 1997, UCAL_OCTOBER, 26, UCAL_SUNDAY, (2*60*60*1000), status); 213 int32_t offset2 = tz->getOffset(1, 214 1997, UCAL_OCTOBER, 26, UCAL_SUNDAY, (2*60*60*1000)-1, status); 215 216 int32_t offset3 = tz->getOffset(1, 217 1997, UCAL_OCTOBER, 26, UCAL_SUNDAY, (1*60*60*1000), status); 218 int32_t offset4 = tz->getOffset(1, 219 1997, UCAL_OCTOBER, 26, UCAL_SUNDAY, (1*60*60*1000)-1, status); 220 221 /* 222 * The following was added just for consistency. It shows that going *to* Daylight 223 * Savings Time (PDT) does work at 2am. 224 */ 225 int32_t offset5 = tz->getOffset(1, 226 1997, UCAL_APRIL, 6, UCAL_SUNDAY, (2*60*60*1000), status); 227 int32_t offset6 = tz->getOffset(1, 228 1997, UCAL_APRIL, 6, UCAL_SUNDAY, (2*60*60*1000)-1, status); 229 int32_t offset5a = tz->getOffset(1, 230 1997, UCAL_APRIL, 6, UCAL_SUNDAY, (3*60*60*1000), status); 231 int32_t offset6a = tz->getOffset(1, 232 1997, UCAL_APRIL, 6, UCAL_SUNDAY, (3*60*60*1000)-1, status); 233 int32_t offset7 = tz->getOffset(1, 234 1997, UCAL_APRIL, 6, UCAL_SUNDAY, (1*60*60*1000), status); 235 int32_t offset8 = tz->getOffset(1, 236 1997, UCAL_APRIL, 6, UCAL_SUNDAY, (1*60*60*1000)-1, status); 237 int32_t SToffset = (int32_t)(-8 * 60*60*1000L); 238 int32_t DToffset = (int32_t)(-7 * 60*60*1000L); 239 240 #define ERR_IF_FAIL(x) if(x) { dataerrln("FAIL: TimeZone misbehaving - %s", #x); } 241 242 ERR_IF_FAIL(U_FAILURE(status)) 243 ERR_IF_FAIL(offset1 != SToffset) 244 ERR_IF_FAIL(offset2 != SToffset) 245 ERR_IF_FAIL(offset3 != SToffset) 246 ERR_IF_FAIL(offset4 != DToffset) 247 ERR_IF_FAIL(offset5 != DToffset) 248 ERR_IF_FAIL(offset6 != SToffset) 249 ERR_IF_FAIL(offset5a != DToffset) 250 ERR_IF_FAIL(offset6a != DToffset) 251 ERR_IF_FAIL(offset7 != SToffset) 252 ERR_IF_FAIL(offset8 != SToffset) 253 254 #undef ERR_IF_FAIL 255 256 delete tz; 257 } 258 259 /** 260 * @bug 4096952 261 */ 262 void TimeZoneRegressionTest:: Test4096952() { 263 // {sfb} serialization not applicable 264 /* 265 UnicodeString ZONES [] = { UnicodeString("GMT"), UnicodeString("MET"), UnicodeString("IST") }; 266 UBool pass = TRUE; 267 //try { 268 for (int32_t i=0; i < ZONES.length; ++i) { 269 TimeZone *zone = TimeZone::createTimeZone(ZONES[i]); 270 UnicodeString id; 271 if (zone->getID(id) != ZONES[i]) 272 errln("Fail: Test broken; zones not instantiating"); 273 274 ByteArrayOutputStream baos; 275 ObjectOutputStream ostream = 276 new ObjectOutputStream(baos = new 277 ByteArrayOutputStream()); 278 ostream.writeObject(zone); 279 ostream.close(); 280 baos.close(); 281 ObjectInputStream istream = 282 new ObjectInputStream(new 283 ByteArrayInputStream(baos.toByteArray())); 284 TimeZone frankenZone = (TimeZone) istream.readObject(); 285 //logln("Zone: " + zone); 286 //logln("FrankenZone: " + frankenZone); 287 if (!zone.equals(frankenZone)) { 288 logln("TimeZone " + zone.getID() + 289 " not equal to serialized/deserialized one"); 290 pass = false; 291 } 292 } 293 if (!pass) errln("Fail: TimeZone serialization/equality bug"); 294 } 295 catch (IOException e) { 296 errln("Fail: " + e); 297 e.print32_tStackTrace(); 298 } 299 catch (ClassNotFoundException e) { 300 errln("Fail: " + e); 301 e.print32_tStackTrace(); 302 } 303 */ 304 } 305 306 /** 307 * @bug 4109314 308 */ 309 void TimeZoneRegressionTest:: Test4109314() { 310 UErrorCode status = U_ZERO_ERROR; 311 GregorianCalendar *testCal = (GregorianCalendar*)Calendar::createInstance(status); 312 if(U_FAILURE(status)) { 313 dataerrln("Error creating calendar %s", u_errorName(status)); 314 delete testCal; 315 return; 316 } 317 failure(status, "Calendar::createInstance"); 318 TimeZone *PST = TimeZone::createTimeZone("PST"); 319 /*Object[] testData = { 320 PST, new Date(98,Calendar.APRIL,4,22,0), new Date(98, Calendar.APRIL, 5,6,0), 321 PST, new Date(98,Calendar.OCTOBER,24,22,0), new Date(98,Calendar.OCTOBER,25,6,0), 322 };*/ 323 UDate testData [] = { 324 CalendarRegressionTest::makeDate(98,UCAL_APRIL,4,22,0), 325 CalendarRegressionTest::makeDate(98, UCAL_APRIL,5,6,0), 326 CalendarRegressionTest::makeDate(98,UCAL_OCTOBER,24,22,0), 327 CalendarRegressionTest::makeDate(98,UCAL_OCTOBER,25,6,0) 328 }; 329 UBool pass = TRUE; 330 for (int32_t i = 0; i < 4; i+=2) { 331 //testCal->setTimeZone((TimeZone) testData[i]); 332 testCal->setTimeZone(*PST); 333 UDate t = testData[i]; 334 UDate end = testData[i+1]; 335 while(testCal->getTime(status) < end) { 336 testCal->setTime(t, status); 337 if ( ! checkCalendar314(testCal, PST)) 338 pass = FALSE; 339 t += 60*60*1000.0; 340 } 341 } 342 if ( ! pass) 343 errln("Fail: TZ API inconsistent"); 344 345 delete testCal; 346 delete PST; 347 } 348 349 UBool 350 TimeZoneRegressionTest::checkCalendar314(GregorianCalendar *testCal, TimeZone *testTZ) 351 { 352 UErrorCode status = U_ZERO_ERROR; 353 // GregorianCalendar testCal = (GregorianCalendar)aCal.clone(); 354 355 int32_t tzOffset, tzRawOffset; 356 float tzOffsetFloat,tzRawOffsetFloat; 357 // Here is where the user made an error. They were passing in the value of 358 // the MILLSECOND field; you need to pass in the millis in the day in STANDARD 359 // time. 360 UDate millis = testCal->get(UCAL_MILLISECOND, status) + 361 1000.0 * (testCal->get(UCAL_SECOND, status) + 362 60.0 * (testCal->get(UCAL_MINUTE, status) + 363 60.0 * (testCal->get(UCAL_HOUR_OF_DAY, status)))) - 364 testCal->get(UCAL_DST_OFFSET, status); 365 366 /* Fix up millis to be in range. ASSUME THAT WE ARE NOT AT THE 367 * BEGINNING OR END OF A MONTH. We must add this code because 368 * getOffset() has been changed to be more strict about the parameters 369 * it receives -- it turns out that this test was passing in illegal 370 * values. */ 371 int32_t date = testCal->get(UCAL_DATE, status); 372 int32_t dow = testCal->get(UCAL_DAY_OF_WEEK, status); 373 while(millis < 0) { 374 millis += U_MILLIS_PER_DAY; 375 --date; 376 dow = UCAL_SUNDAY + ((dow - UCAL_SUNDAY + 6) % 7); 377 } 378 while (millis >= U_MILLIS_PER_DAY) { 379 millis -= U_MILLIS_PER_DAY; 380 ++date; 381 dow = UCAL_SUNDAY + ((dow - UCAL_SUNDAY + 1) % 7); 382 } 383 384 tzOffset = testTZ->getOffset((uint8_t)testCal->get(UCAL_ERA, status), 385 testCal->get(UCAL_YEAR, status), 386 testCal->get(UCAL_MONTH, status), 387 date, 388 (uint8_t)dow, 389 (int32_t)millis, 390 status); 391 tzRawOffset = testTZ->getRawOffset(); 392 tzOffsetFloat = (float)tzOffset/(float)3600000; 393 tzRawOffsetFloat = (float)tzRawOffset/(float)3600000; 394 395 UDate testDate = testCal->getTime(status); 396 397 UBool inDaylightTime = testTZ->inDaylightTime(testDate, status); 398 SimpleDateFormat *sdf = new SimpleDateFormat((UnicodeString)"MM/dd/yyyy HH:mm", status); 399 sdf->setCalendar(*testCal); 400 UnicodeString inDaylightTimeString; 401 402 UBool passed; 403 404 if(inDaylightTime) 405 { 406 inDaylightTimeString = " DST "; 407 passed = (tzOffset == (tzRawOffset + 3600000)); 408 } 409 else 410 { 411 inDaylightTimeString = " "; 412 passed = (tzOffset == tzRawOffset); 413 } 414 415 UnicodeString output; 416 FieldPosition pos(0); 417 output = testTZ->getID(output) + " " + sdf->format(testDate, output, pos) + 418 " Offset(" + tzOffsetFloat + ")" + 419 " RawOffset(" + tzRawOffsetFloat + ")" + 420 " " + millis/(float)3600000 + " " + 421 inDaylightTimeString; 422 423 if (passed) 424 output += " "; 425 else 426 output += "ERROR"; 427 428 if (passed) 429 logln(output); 430 else 431 errln(output); 432 433 delete sdf; 434 return passed; 435 } 436 437 /** 438 * @bug 4126678 439 * CANNOT REPRODUDE 440 * 441 * Yet another _alleged_ bug in TimeZone::getOffset(), a method that never 442 * should have been made public. It's simply too hard to use correctly. 443 * 444 * The original test code failed to do the following: 445 * (1) Call Calendar::setTime() before getting the fields! 446 * (2) Use the right millis (as usual) for getOffset(); they were passing 447 * in the MILLIS field, instead of the STANDARD MILLIS IN DAY. 448 * When you fix these two problems, the test passes, as expected. 449 */ 450 void TimeZoneRegressionTest:: Test4126678() 451 { 452 UErrorCode status = U_ZERO_ERROR; 453 Calendar *cal = Calendar::createInstance(status); 454 if(U_FAILURE(status)) { 455 dataerrln("Error creating calendar %s", u_errorName(status)); 456 delete cal; 457 return; 458 } 459 failure(status, "Calendar::createInstance"); 460 TimeZone *tz = TimeZone::createTimeZone("PST"); 461 cal->adoptTimeZone(tz); 462 463 cal->set(1998, UCAL_APRIL, 5, 10, 0); 464 465 if (! tz->useDaylightTime() || U_FAILURE(status)) 466 dataerrln("We're not in Daylight Savings Time and we should be. - %s", u_errorName(status)); 467 468 //cal.setTime(dt); 469 int32_t era = cal->get(UCAL_ERA, status); 470 int32_t year = cal->get(UCAL_YEAR, status); 471 int32_t month = cal->get(UCAL_MONTH, status); 472 int32_t day = cal->get(UCAL_DATE, status); 473 int32_t dayOfWeek = cal->get(UCAL_DAY_OF_WEEK, status); 474 int32_t millis = cal->get(UCAL_MILLISECOND, status) + 475 (cal->get(UCAL_SECOND, status) + 476 (cal->get(UCAL_MINUTE, status) + 477 (cal->get(UCAL_HOUR, status) * 60) * 60) * 1000) - 478 cal->get(UCAL_DST_OFFSET, status); 479 480 failure(status, "cal->get"); 481 int32_t offset = tz->getOffset((uint8_t)era, year, month, day, (uint8_t)dayOfWeek, millis, status); 482 int32_t raw_offset = tz->getRawOffset(); 483 484 if (offset == raw_offset) 485 errln("Offsets should match"); 486 487 delete cal; 488 } 489 490 /** 491 * @bug 4151406 492 * TimeZone::getAvailableIDs(int32_t) throws exception for certain values, 493 * due to a faulty constant in TimeZone::java. 494 */ 495 void TimeZoneRegressionTest:: Test4151406() { 496 int32_t max = 0; 497 for (int32_t h=-28; h<=30; ++h) { 498 // h is in half-hours from GMT; rawoffset is in millis 499 int32_t rawoffset = h * 1800000; 500 int32_t hh = (h<0) ? -h : h; 501 UnicodeString hname = UnicodeString((h<0) ? "GMT-" : "GMT+") + 502 ((hh/2 < 10) ? "0" : "") + 503 (hh/2) + ':' + 504 ((hh%2==0) ? "00" : "30"); 505 //try { 506 UErrorCode ec = U_ZERO_ERROR; 507 int32_t count; 508 StringEnumeration* ids = TimeZone::createEnumeration(rawoffset); 509 count = ids->count(ec); 510 if (count> max) 511 max = count; 512 if (count > 0) { 513 logln(hname + ' ' + (UnicodeString)count + (UnicodeString)" e.g. " + *ids->snext(ec)); 514 } else { 515 logln(hname + ' ' + count); 516 } 517 // weiv 11/27/2002: why uprv_free? This should be a delete 518 delete ids; 519 //delete [] ids; 520 //uprv_free(ids); 521 /*} catch (Exception e) { 522 errln(hname + ' ' + "Fail: " + e); 523 }*/ 524 } 525 logln("Maximum zones per offset = %d", max); 526 } 527 528 /** 529 * @bug 4151429 530 */ 531 void TimeZoneRegressionTest:: Test4151429() { 532 // {sfb} silly test in C++, since we are using an enum and not an int 533 //try { 534 /*TimeZone *tz = TimeZone::createTimeZone("GMT"); 535 UnicodeString name; 536 tz->getDisplayName(TRUE, TimeZone::LONG, 537 Locale.getDefault(), name); 538 errln("IllegalArgumentException not thrown by TimeZone::getDisplayName()");*/ 539 //} catch(IllegalArgumentException e) {} 540 } 541 542 /** 543 * @bug 4154537 544 * SimpleTimeZone::hasSameRules() doesn't work for zones with no DST 545 * and different DST parameters. 546 */ 547 void TimeZoneRegressionTest:: Test4154537() { 548 UErrorCode status = U_ZERO_ERROR; 549 // tz1 and tz2 have no DST and different rule parameters 550 SimpleTimeZone *tz1 = new SimpleTimeZone(0, "1", 0, 0, 0, 0, 2, 0, 0, 0, status); 551 SimpleTimeZone *tz2 = new SimpleTimeZone(0, "2", 1, 0, 0, 0, 3, 0, 0, 0, status); 552 // tza and tzA have the same rule params 553 SimpleTimeZone *tza = new SimpleTimeZone(0, "a", 0, 1, 0, 0, 3, 2, 0, 0, status); 554 SimpleTimeZone *tzA = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 3, 2, 0, 0, status); 555 // tzb differs from tza 556 SimpleTimeZone *tzb = new SimpleTimeZone(0, "b", 0, 1, 0, 0, 3, 1, 0, 0, status); 557 558 if(U_FAILURE(status)) 559 errln("Couldn't create TimeZones"); 560 561 if (tz1->useDaylightTime() || tz2->useDaylightTime() || 562 !tza->useDaylightTime() || !tzA->useDaylightTime() || 563 !tzb->useDaylightTime()) { 564 errln("Test is broken -- rewrite it"); 565 } 566 if (!tza->hasSameRules(*tzA) || tza->hasSameRules(*tzb)) { 567 errln("Fail: hasSameRules() broken for zones with rules"); 568 } 569 if (!tz1->hasSameRules(*tz2)) { 570 errln("Fail: hasSameRules() returns false for zones without rules"); 571 //errln("zone 1 = " + tz1); 572 //errln("zone 2 = " + tz2); 573 } 574 575 delete tz1; 576 delete tz2; 577 delete tza; 578 delete tzA; 579 delete tzb; 580 } 581 582 /** 583 * @bug 4154542 584 * SimpleTimeZOne constructors, setStartRule(), and setEndRule() don't 585 * check for out-of-range arguments. 586 */ 587 void TimeZoneRegressionTest:: Test4154542() 588 { 589 const int32_t GOOD = 1; 590 const int32_t BAD = 0; 591 592 const int32_t GOOD_MONTH = UCAL_JANUARY; 593 const int32_t GOOD_DAY = 1; 594 const int32_t GOOD_DAY_OF_WEEK = UCAL_SUNDAY; 595 const int32_t GOOD_TIME = 0; 596 597 int32_t DATA [] = { 598 GOOD, INT32_MIN, 0, INT32_MAX, INT32_MIN, 599 GOOD, UCAL_JANUARY, -5, UCAL_SUNDAY, 0, 600 GOOD, UCAL_DECEMBER, 5, UCAL_SATURDAY, 24*60*60*1000, 601 BAD, UCAL_DECEMBER, 5, UCAL_SATURDAY, 24*60*60*1000+1, 602 BAD, UCAL_DECEMBER, 5, UCAL_SATURDAY, -1, 603 BAD, UCAL_JANUARY, -6, UCAL_SUNDAY, 0, 604 BAD, UCAL_DECEMBER, 6, UCAL_SATURDAY, 24*60*60*1000, 605 GOOD, UCAL_DECEMBER, 1, 0, 0, 606 GOOD, UCAL_DECEMBER, 31, 0, 0, 607 BAD, UCAL_APRIL, 31, 0, 0, 608 BAD, UCAL_DECEMBER, 32, 0, 0, 609 BAD, UCAL_JANUARY-1, 1, UCAL_SUNDAY, 0, 610 BAD, UCAL_DECEMBER+1, 1, UCAL_SUNDAY, 0, 611 GOOD, UCAL_DECEMBER, 31, -UCAL_SUNDAY, 0, 612 GOOD, UCAL_DECEMBER, 31, -UCAL_SATURDAY, 0, 613 BAD, UCAL_DECEMBER, 32, -UCAL_SATURDAY, 0, 614 BAD, UCAL_DECEMBER, -32, -UCAL_SATURDAY, 0, 615 BAD, UCAL_DECEMBER, 31, -UCAL_SATURDAY-1, 0, 616 }; 617 SimpleTimeZone *zone = new SimpleTimeZone(0, "Z"); 618 for (int32_t i=0; i < 18*5; i+=5) { 619 UBool shouldBeGood = (DATA[i] == GOOD); 620 int32_t month = DATA[i+1]; 621 int32_t day = DATA[i+2]; 622 int32_t dayOfWeek = DATA[i+3]; 623 int32_t time = DATA[i+4]; 624 625 UErrorCode status = U_ZERO_ERROR; 626 627 //Exception ex = null; 628 //try { 629 zone->setStartRule(month, day, dayOfWeek, time, status); 630 //} catch (IllegalArgumentException e) { 631 // ex = e; 632 //} 633 if (U_SUCCESS(status) != shouldBeGood) { 634 errln(UnicodeString("setStartRule(month=") + month + ", day=" + day + 635 ", dayOfWeek=" + dayOfWeek + ", time=" + time + 636 (shouldBeGood ? (") should work") 637 : ") should fail but doesn't")); 638 } 639 640 //ex = null; 641 //try { 642 status = U_ZERO_ERROR; 643 zone->setEndRule(month, day, dayOfWeek, time, status); 644 //} catch (IllegalArgumentException e) { 645 // ex = e; 646 //} 647 if (U_SUCCESS(status) != shouldBeGood) { 648 errln(UnicodeString("setEndRule(month=") + month + ", day=" + day + 649 ", dayOfWeek=" + dayOfWeek + ", time=" + time + 650 (shouldBeGood ? (") should work") 651 : ") should fail but doesn't")); 652 } 653 654 //ex = null; 655 //try { 656 // {sfb} need to look into ctor problems! (UErrorCode vs. dst signature confusion) 657 status = U_ZERO_ERROR; 658 SimpleTimeZone *temp = new SimpleTimeZone(0, "Z", 659 (int8_t)month, (int8_t)day, (int8_t)dayOfWeek, time, 660 (int8_t)GOOD_MONTH, (int8_t)GOOD_DAY, (int8_t)GOOD_DAY_OF_WEEK, 661 GOOD_TIME,status); 662 //} catch (IllegalArgumentException e) { 663 // ex = e; 664 //} 665 if (U_SUCCESS(status) != shouldBeGood) { 666 errln(UnicodeString("SimpleTimeZone(month=") + month + ", day=" + day + 667 ", dayOfWeek=" + dayOfWeek + ", time=" + time + 668 (shouldBeGood ? (", <end>) should work")// + ex) 669 : ", <end>) should fail but doesn't")); 670 } 671 672 delete temp; 673 //ex = null; 674 //try { 675 status = U_ZERO_ERROR; 676 temp = new SimpleTimeZone(0, "Z", 677 (int8_t)GOOD_MONTH, (int8_t)GOOD_DAY, (int8_t)GOOD_DAY_OF_WEEK, 678 GOOD_TIME, 679 (int8_t)month, (int8_t)day, (int8_t)dayOfWeek, time,status); 680 //} catch (IllegalArgumentException e) { 681 // ex = e; 682 //} 683 if (U_SUCCESS(status) != shouldBeGood) { 684 errln(UnicodeString("SimpleTimeZone(<start>, month=") + month + ", day=" + day + 685 ", dayOfWeek=" + dayOfWeek + ", time=" + time + 686 (shouldBeGood ? (") should work")// + ex) 687 : ") should fail but doesn't")); 688 } 689 delete temp; 690 } 691 delete zone; 692 } 693 694 695 /** 696 * @bug 4154525 697 * SimpleTimeZone accepts illegal DST savings values. These values 698 * must be non-zero. There is no upper limit at this time. 699 */ 700 void 701 TimeZoneRegressionTest::Test4154525() 702 { 703 const int32_t GOOD = 1, BAD = 0; 704 705 int32_t DATA [] = { 706 1, GOOD, 707 0, BAD, 708 -1, BAD, 709 60*60*1000, GOOD, 710 INT32_MIN, BAD, 711 // Integer.MAX_VALUE, ?, // no upper limit on DST savings at this time 712 }; 713 714 UErrorCode status = U_ZERO_ERROR; 715 for(int32_t i = 0; i < 10; i+=2) { 716 int32_t savings = DATA[i]; 717 UBool valid = DATA[i+1] == GOOD; 718 UnicodeString method; 719 for(int32_t j=0; j < 2; ++j) { 720 SimpleTimeZone *z=NULL; 721 switch (j) { 722 case 0: 723 method = "constructor"; 724 z = new SimpleTimeZone(0, "id", 725 UCAL_JANUARY, 1, 0, 0, 726 UCAL_MARCH, 1, 0, 0, 727 savings, status); // <- what we're interested in 728 break; 729 case 1: 730 method = "setDSTSavings()"; 731 z = new SimpleTimeZone(0, "GMT"); 732 z->setDSTSavings(savings, status); 733 break; 734 } 735 736 if(U_FAILURE(status)) { 737 if(valid) { 738 errln(UnicodeString("Fail: DST savings of ") + savings + " to " + method + " gave " + u_errorName(status)); 739 } 740 else { 741 logln(UnicodeString("Pass: DST savings of ") + savings + " to " + method + " gave " + u_errorName(status)); 742 } 743 } 744 else { 745 if(valid) { 746 logln(UnicodeString("Pass: DST savings of ") + savings + " accepted by " + method); 747 } 748 else { 749 errln(UnicodeString("Fail: DST savings of ") + savings + " accepted by " + method); 750 } 751 } 752 status = U_ZERO_ERROR; 753 delete z; 754 } 755 } 756 } 757 758 /** 759 * @bug 4154650 760 * SimpleTimeZone.getOffset accepts illegal arguments. 761 */ 762 void 763 TimeZoneRegressionTest::Test4154650() 764 { 765 const int32_t GOOD = 1, BAD = 0; 766 const int32_t GOOD_ERA = GregorianCalendar::AD, GOOD_YEAR = 1998, GOOD_MONTH = UCAL_AUGUST; 767 const int32_t GOOD_DAY = 2, GOOD_DOW = UCAL_SUNDAY, GOOD_TIME = 16*3600000; 768 769 int32_t DATA []= { 770 GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, 771 772 GOOD, GregorianCalendar::BC, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, 773 GOOD, GregorianCalendar::AD, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, 774 BAD, GregorianCalendar::BC-1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, 775 BAD, GregorianCalendar::AD+1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, 776 777 GOOD, GOOD_ERA, GOOD_YEAR, UCAL_JANUARY, GOOD_DAY, GOOD_DOW, GOOD_TIME, 778 GOOD, GOOD_ERA, GOOD_YEAR, UCAL_DECEMBER, GOOD_DAY, GOOD_DOW, GOOD_TIME, 779 BAD, GOOD_ERA, GOOD_YEAR, UCAL_JANUARY-1, GOOD_DAY, GOOD_DOW, GOOD_TIME, 780 BAD, GOOD_ERA, GOOD_YEAR, UCAL_DECEMBER+1, GOOD_DAY, GOOD_DOW, GOOD_TIME, 781 782 GOOD, GOOD_ERA, GOOD_YEAR, UCAL_JANUARY, 1, GOOD_DOW, GOOD_TIME, 783 GOOD, GOOD_ERA, GOOD_YEAR, UCAL_JANUARY, 31, GOOD_DOW, GOOD_TIME, 784 BAD, GOOD_ERA, GOOD_YEAR, UCAL_JANUARY, 0, GOOD_DOW, GOOD_TIME, 785 BAD, GOOD_ERA, GOOD_YEAR, UCAL_JANUARY, 32, GOOD_DOW, GOOD_TIME, 786 787 GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, UCAL_SUNDAY, GOOD_TIME, 788 GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, UCAL_SATURDAY, GOOD_TIME, 789 BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, UCAL_SUNDAY-1, GOOD_TIME, 790 BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, UCAL_SATURDAY+1, GOOD_TIME, 791 792 GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 0, 793 GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000-1, 794 BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, -1, 795 BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000, 796 }; 797 798 int32_t dataLen = (int32_t)(sizeof(DATA) / sizeof(DATA[0])); 799 800 UErrorCode status = U_ZERO_ERROR; 801 TimeZone *tz = TimeZone::createDefault(); 802 for(int32_t i = 0; i < dataLen; i += 7) { 803 UBool good = DATA[i] == GOOD; 804 //IllegalArgumentException e = null; 805 //try { 806 /*int32_t offset = */ 807 tz->getOffset((uint8_t)DATA[i+1], DATA[i+2], DATA[i+3], 808 DATA[i+4], (uint8_t)DATA[i+5], DATA[i+6], status); 809 //} catch (IllegalArgumentException ex) { 810 // e = ex; 811 //} 812 if(good != U_SUCCESS(status)) { 813 UnicodeString errMsg; 814 if (good) { 815 errMsg = (UnicodeString(") threw ") + u_errorName(status)); 816 } 817 else { 818 errMsg = UnicodeString(") accepts invalid args", ""); 819 } 820 errln(UnicodeString("Fail: getOffset(") + 821 DATA[i+1] + ", " + DATA[i+2] + ", " + DATA[i+3] + ", " + 822 DATA[i+4] + ", " + DATA[i+5] + ", " + DATA[i+6] + 823 errMsg); 824 } 825 status = U_ZERO_ERROR; // reset 826 } 827 delete tz; 828 } 829 830 /** 831 * @bug 4162593 832 * TimeZone broken at midnight. The TimeZone code fails to handle 833 * transitions at midnight correctly. 834 */ 835 void 836 TimeZoneRegressionTest::Test4162593() 837 { 838 UErrorCode status = U_ZERO_ERROR; 839 SimpleDateFormat *fmt = new SimpleDateFormat("z", Locale::getUS(), status); 840 if(U_FAILURE(status)) { 841 dataerrln("Error creating calendar %s", u_errorName(status)); 842 delete fmt; 843 return; 844 } 845 const int32_t ONE_HOUR = 60*60*1000; 846 847 SimpleTimeZone *asuncion = new SimpleTimeZone(-4*ONE_HOUR, "America/Asuncion" /*PY%sT*/, 848 UCAL_OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR, 849 UCAL_MARCH, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR, status); 850 851 /* Zone 852 * Starting time 853 * Transition expected between start+1H and start+2H 854 */ 855 TimeZone *DATA_TZ [] = { 856 0, 0, 0 }; 857 858 int32_t DATA_INT [] [5] = { 859 // These years must be AFTER the Gregorian cutover 860 {1998, UCAL_SEPTEMBER, 30, 22, 0}, 861 {2000, UCAL_FEBRUARY, 28, 22, 0}, 862 {2000, UCAL_FEBRUARY, 29, 22, 0}, 863 }; 864 865 UBool DATA_BOOL [] = { 866 TRUE, 867 FALSE, 868 TRUE, 869 }; 870 871 UnicodeString zone [4];// = new String[4]; 872 DATA_TZ[0] = 873 new SimpleTimeZone(2*ONE_HOUR, "Asia/Damascus" /*EE%sT*/, 874 UCAL_APRIL, 1, 0 /*DOM*/, 0*ONE_HOUR, 875 UCAL_OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR, status); 876 DATA_TZ[1] = asuncion; DATA_TZ[2] = asuncion; 877 878 for(int32_t j = 0; j < 3; j++) { 879 TimeZone *tz = (TimeZone*)DATA_TZ[j]; 880 TimeZone::setDefault(*tz); 881 fmt->setTimeZone(*tz); 882 883 // Must construct the Date object AFTER setting the default zone 884 int32_t *p = (int32_t*)DATA_INT[j]; 885 UDate d = CalendarRegressionTest::makeDate(p[0], p[1], p[2], p[3], p[4]); 886 UBool transitionExpected = DATA_BOOL[j]; 887 888 UnicodeString temp; 889 logln(tz->getID(temp) + ":"); 890 for (int32_t i = 0; i < 4; ++i) { 891 FieldPosition pos(0); 892 zone[i].remove(); 893 zone[i] = fmt->format(d+ i*ONE_HOUR, zone[i], pos); 894 logln(UnicodeString("") + i + ": " + d + " / " + zone[i]); 895 //d += (double) ONE_HOUR; 896 } 897 if(zone[0] == zone[1] && 898 (zone[1] == zone[2]) != transitionExpected && 899 zone[2] == zone[3]) { 900 logln(UnicodeString("Ok: transition ") + transitionExpected); 901 } 902 else { 903 errln("Fail: boundary transition incorrect"); 904 } 905 } 906 delete fmt; 907 delete asuncion; 908 delete DATA_TZ[0]; 909 } 910 911 /** 912 * getDisplayName doesn't work with unusual savings/offsets. 913 */ 914 void TimeZoneRegressionTest::Test4176686() { 915 // Construct a zone that does not observe DST but 916 // that does have a DST savings (which should be ignored). 917 UErrorCode status = U_ZERO_ERROR; 918 int32_t offset = 90 * 60000; // 1:30 919 SimpleTimeZone* z1 = new SimpleTimeZone(offset, "_std_zone_"); 920 z1->setDSTSavings(45 * 60000, status); // 0:45 921 922 // Construct a zone that observes DST for the first 6 months. 923 SimpleTimeZone* z2 = new SimpleTimeZone(offset, "_dst_zone_"); 924 z2->setDSTSavings(45 * 60000, status); // 0:45 925 z2->setStartRule(UCAL_JANUARY, 1, 0, status); 926 z2->setEndRule(UCAL_JULY, 1, 0, status); 927 928 // Also check DateFormat 929 DateFormat* fmt1 = new SimpleDateFormat(UnicodeString("z"), status); 930 if (U_FAILURE(status)) { 931 dataerrln("Failure trying to construct: %s", u_errorName(status)); 932 return; 933 } 934 fmt1->setTimeZone(*z1); // Format uses standard zone 935 DateFormat* fmt2 = new SimpleDateFormat(UnicodeString("z"), status); 936 if(!assertSuccess("trying to construct", status))return; 937 fmt2->setTimeZone(*z2); // Format uses DST zone 938 Calendar* tempcal = Calendar::createInstance(status); 939 tempcal->clear(); 940 tempcal->set(1970, UCAL_FEBRUARY, 1); 941 UDate dst = tempcal->getTime(status); // Time in DST 942 tempcal->set(1970, UCAL_AUGUST, 1); 943 UDate std = tempcal->getTime(status); // Time in standard 944 945 // Description, Result, Expected Result 946 UnicodeString a,b,c,d,e,f,g,h,i,j,k,l; 947 UnicodeString DATA[] = { 948 "z1->getDisplayName(false, SHORT)/std zone", 949 z1->getDisplayName(FALSE, TimeZone::SHORT, a), "GMT+01:30", 950 "z1->getDisplayName(false, LONG)/std zone", 951 z1->getDisplayName(FALSE, TimeZone::LONG, b), "GMT+01:30", 952 "z1->getDisplayName(true, SHORT)/std zone", 953 z1->getDisplayName(TRUE, TimeZone::SHORT, c), "GMT+01:30", 954 "z1->getDisplayName(true, LONG)/std zone", 955 z1->getDisplayName(TRUE, TimeZone::LONG, d ), "GMT+01:30", 956 "z2->getDisplayName(false, SHORT)/dst zone", 957 z2->getDisplayName(FALSE, TimeZone::SHORT, e), "GMT+01:30", 958 "z2->getDisplayName(false, LONG)/dst zone", 959 z2->getDisplayName(FALSE, TimeZone::LONG, f ), "GMT+01:30", 960 "z2->getDisplayName(true, SHORT)/dst zone", 961 z2->getDisplayName(TRUE, TimeZone::SHORT, g), "GMT+02:15", 962 "z2->getDisplayName(true, LONG)/dst zone", 963 z2->getDisplayName(TRUE, TimeZone::LONG, h ), "GMT+02:15", 964 "DateFormat.format(std)/std zone", fmt1->format(std, i), "GMT+01:30", 965 "DateFormat.format(dst)/std zone", fmt1->format(dst, j), "GMT+01:30", 966 "DateFormat.format(std)/dst zone", fmt2->format(std, k), "GMT+01:30", 967 "DateFormat.format(dst)/dst zone", fmt2->format(dst, l), "GMT+02:15", 968 }; 969 970 for (int32_t idx=0; idx<(int32_t)ARRAY_LENGTH(DATA); idx+=3) { 971 if (DATA[idx+1]!=(DATA[idx+2])) { 972 errln("FAIL: " + DATA[idx] + " -> " + DATA[idx+1] + ", exp " + DATA[idx+2]); 973 } 974 } 975 delete z1; 976 delete z2; 977 delete fmt1; 978 delete fmt2; 979 delete tempcal; 980 } 981 982 /** 983 * Make sure setStartRule and setEndRule set the DST savings to nonzero 984 * if it was zero. 985 */ 986 void TimeZoneRegressionTest::TestJ186() { 987 UErrorCode status = U_ZERO_ERROR; 988 // NOTE: Setting the DST savings to zero is illegal, so we 989 // are limited in the testing we can do here. This is why 990 // lines marked //~ are commented out. 991 SimpleTimeZone z(0, "ID"); 992 //~z.setDSTSavings(0, status); // Must do this! 993 z.setStartRule(UCAL_FEBRUARY, 1, UCAL_SUNDAY, 0, status); 994 failure(status, "setStartRule()"); 995 if (z.useDaylightTime()) { 996 errln("Fail: useDaylightTime true with start rule only"); 997 } 998 //~if (z.getDSTSavings() != 0) { 999 //~ errln("Fail: dst savings != 0 with start rule only"); 1000 //~} 1001 z.setEndRule(UCAL_MARCH, -1, UCAL_SUNDAY, 0, status); 1002 failure(status, "setStartRule()"); 1003 if (!z.useDaylightTime()) { 1004 errln("Fail: useDaylightTime false with rules set"); 1005 } 1006 if (z.getDSTSavings() == 0) { 1007 errln("Fail: dst savings == 0 with rules set"); 1008 } 1009 } 1010 1011 /** 1012 * Test to see if DateFormat understands zone equivalency groups. It 1013 * might seem that this should be a DateFormat test, but it's really a 1014 * TimeZone test -- the changes to DateFormat are minor. 1015 * 1016 * We use two known, stable zones that shouldn't change much over time 1017 * -- America/Vancouver and America/Los_Angeles. However, they MAY 1018 * change at some point -- if that happens, replace them with any two 1019 * zones in an equivalency group where one zone has localized name 1020 * data, and the other doesn't, in some locale. 1021 */ 1022 void TimeZoneRegressionTest::TestJ449() { 1023 UErrorCode status = U_ZERO_ERROR; 1024 UnicodeString str; 1025 1026 // Modify the following three as necessary. The two IDs must 1027 // specify two zones in the same equivalency group. One must have 1028 // locale data in 'loc'; the other must not. 1029 const char* idWithLocaleData = "America/Los_Angeles"; 1030 const char* idWithoutLocaleData = "US/Pacific"; 1031 const Locale loc("en", "", ""); 1032 1033 TimeZone *zoneWith = TimeZone::createTimeZone(idWithLocaleData); 1034 TimeZone *zoneWithout = TimeZone::createTimeZone(idWithoutLocaleData); 1035 // Make sure we got valid zones 1036 if (zoneWith->getID(str) != UnicodeString(idWithLocaleData) || 1037 zoneWithout->getID(str) != UnicodeString(idWithoutLocaleData)) { 1038 dataerrln(UnicodeString("Fail: Unable to create zones - wanted ") + idWithLocaleData + ", got " + zoneWith->getID(str) + ", and wanted " + idWithoutLocaleData + " but got " + zoneWithout->getID(str)); 1039 } else { 1040 GregorianCalendar calWith(*zoneWith, status); 1041 GregorianCalendar calWithout(*zoneWithout, status); 1042 SimpleDateFormat fmt("MMM d yyyy hh:mm a zzz", loc, status); 1043 if (U_FAILURE(status)) { 1044 errln("Fail: Unable to create GregorianCalendar/SimpleDateFormat"); 1045 } else { 1046 UDate date = 0; 1047 UnicodeString strWith, strWithout; 1048 fmt.setCalendar(calWith); 1049 fmt.format(date, strWith); 1050 fmt.setCalendar(calWithout); 1051 fmt.format(date, strWithout); 1052 if (strWith == strWithout) { 1053 logln((UnicodeString)"Ok: " + idWithLocaleData + " -> " + 1054 strWith + "; " + idWithoutLocaleData + " -> " + 1055 strWithout); 1056 } else { 1057 errln((UnicodeString)"FAIL: " + idWithLocaleData + " -> " + 1058 strWith + "; " + idWithoutLocaleData + " -> " + 1059 strWithout); 1060 } 1061 } 1062 } 1063 1064 delete zoneWith; 1065 delete zoneWithout; 1066 } 1067 1068 // test new API for JDK 1.2 8/31 putback 1069 void 1070 TimeZoneRegressionTest::TestJDK12API() 1071 { 1072 // TimeZone *pst = TimeZone::createTimeZone("PST"); 1073 // TimeZone *cst1 = TimeZone::createTimeZone("CST"); 1074 UErrorCode ec = U_ZERO_ERROR; 1075 //d,-28800,3,1,-1,120,w,9,-1,1,120,w,60 1076 TimeZone *pst = new SimpleTimeZone(-28800*U_MILLIS_PER_SECOND, 1077 "PST", 1078 3,1,-1,120*U_MILLIS_PER_MINUTE, 1079 SimpleTimeZone::WALL_TIME, 1080 9,-1,1,120*U_MILLIS_PER_MINUTE, 1081 SimpleTimeZone::WALL_TIME, 1082 60*U_MILLIS_PER_MINUTE,ec); 1083 //d,-21600,3,1,-1,120,w,9,-1,1,120,w,60 1084 TimeZone *cst1 = new SimpleTimeZone(-21600*U_MILLIS_PER_SECOND, 1085 "CST", 1086 3,1,-1,120*U_MILLIS_PER_MINUTE, 1087 SimpleTimeZone::WALL_TIME, 1088 9,-1,1,120*U_MILLIS_PER_MINUTE, 1089 SimpleTimeZone::WALL_TIME, 1090 60*U_MILLIS_PER_MINUTE,ec); 1091 if (U_FAILURE(ec)) { 1092 errln("FAIL: SimpleTimeZone constructor"); 1093 return; 1094 } 1095 1096 SimpleTimeZone *cst = dynamic_cast<SimpleTimeZone *>(cst1); 1097 1098 if(pst->hasSameRules(*cst)) { 1099 errln("FAILURE: PST and CST have same rules"); 1100 } 1101 1102 UErrorCode status = U_ZERO_ERROR; 1103 int32_t offset1 = pst->getOffset(1, 1104 1997, UCAL_OCTOBER, 26, UCAL_SUNDAY, (2*60*60*1000), status); 1105 failure(status, "getOffset() failed"); 1106 1107 1108 int32_t offset2 = cst->getOffset(1, 1109 1997, UCAL_OCTOBER, 26, UCAL_SUNDAY, (2*60*60*1000), 31, status); 1110 failure(status, "getOffset() failed"); 1111 1112 if(offset1 == offset2) 1113 errln("FAILURE: Sunday Oct. 26 1997 2:00 has same offset for PST and CST"); 1114 1115 // verify error checking 1116 pst->getOffset(1, 1117 1997, UCAL_FIELD_COUNT+1, 26, UCAL_SUNDAY, (2*60*60*1000), status); 1118 if(U_SUCCESS(status)) 1119 errln("FAILURE: getOffset() succeeded with -1 for month"); 1120 1121 status = U_ZERO_ERROR; 1122 cst->setDSTSavings(60*60*1000, status); 1123 failure(status, "setDSTSavings() failed"); 1124 1125 int32_t savings = cst->getDSTSavings(); 1126 if(savings != 60*60*1000) { 1127 errln("setDSTSavings() failed"); 1128 } 1129 1130 delete pst; 1131 delete cst; 1132 } 1133 /** 1134 * SimpleTimeZone allows invalid DOM values. 1135 */ 1136 void TimeZoneRegressionTest::Test4184229() { 1137 SimpleTimeZone* zone = NULL; 1138 UErrorCode status = U_ZERO_ERROR; 1139 zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0, status); 1140 if(U_SUCCESS(status)){ 1141 errln("Failed. No exception has been thrown for DOM -1 startDay"); 1142 }else{ 1143 logln("(a) " + UnicodeString( u_errorName(status))); 1144 } 1145 status = U_ZERO_ERROR; 1146 delete zone; 1147 1148 zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0, status); 1149 if(U_SUCCESS(status)){ 1150 errln("Failed. No exception has been thrown for DOM -1 endDay"); 1151 }else{ 1152 logln("(b) " + UnicodeString(u_errorName(status))); 1153 } 1154 status = U_ZERO_ERROR; 1155 delete zone; 1156 1157 zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 1000, status); 1158 if(U_SUCCESS(status)){ 1159 errln("Failed. No exception has been thrown for DOM -1 startDay+savings"); 1160 }else{ 1161 logln("(c) " + UnicodeString(u_errorName(status))); 1162 } 1163 status = U_ZERO_ERROR; 1164 delete zone; 1165 zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0, 1000, status); 1166 if(U_SUCCESS(status)){ 1167 errln("Failed. No exception has been thrown for DOM -1 endDay+ savings"); 1168 }else{ 1169 logln("(d) " + UnicodeString(u_errorName(status))); 1170 } 1171 status = U_ZERO_ERROR; 1172 delete zone; 1173 // Make a valid constructor call for subsequent tests. 1174 zone = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 0, 1, 0, 0, status); 1175 1176 zone->setStartRule(0, -1, 0, 0, status); 1177 if(U_SUCCESS(status)){ 1178 errln("Failed. No exception has been thrown for DOM -1 setStartRule +savings"); 1179 } else{ 1180 logln("(e) " + UnicodeString(u_errorName(status))); 1181 } 1182 zone->setStartRule(0, -1, 0, status); 1183 if(U_SUCCESS(status)){ 1184 errln("Failed. No exception has been thrown for DOM -1 setStartRule"); 1185 } else{ 1186 logln("(f) " + UnicodeString(u_errorName(status))); 1187 } 1188 1189 zone->setEndRule(0, -1, 0, 0, status); 1190 if(U_SUCCESS(status)){ 1191 errln("Failed. No exception has been thrown for DOM -1 setEndRule+savings"); 1192 } else{ 1193 logln("(g) " + UnicodeString(u_errorName(status))); 1194 } 1195 1196 zone->setEndRule(0, -1, 0, status); 1197 if(U_SUCCESS(status)){ 1198 errln("Failed. No exception has been thrown for DOM -1 setEndRule"); 1199 } else{ 1200 logln("(h) " + UnicodeString(u_errorName(status))); 1201 } 1202 delete zone; 1203 } 1204 1205 #endif /* #if !UCONFIG_NO_FORMATTING */ 1206