1 /******************************************************************** 2 * Copyright (c) 1997-2011, 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 dataerrln("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 if (ids == NULL) { 510 dataerrln("Fail: TimeZone::createEnumeration(rawoffset)"); 511 continue; 512 } 513 count = ids->count(ec); 514 if (count> max) 515 max = count; 516 if (count > 0) { 517 logln(hname + ' ' + (UnicodeString)count + (UnicodeString)" e.g. " + *ids->snext(ec)); 518 } else { 519 logln(hname + ' ' + count); 520 } 521 // weiv 11/27/2002: why uprv_free? This should be a delete 522 delete ids; 523 //delete [] ids; 524 //uprv_free(ids); 525 /*} catch (Exception e) { 526 errln(hname + ' ' + "Fail: " + e); 527 }*/ 528 } 529 logln("Maximum zones per offset = %d", max); 530 } 531 532 /** 533 * @bug 4151429 534 */ 535 void TimeZoneRegressionTest:: Test4151429() { 536 // {sfb} silly test in C++, since we are using an enum and not an int 537 //try { 538 /*TimeZone *tz = TimeZone::createTimeZone("GMT"); 539 UnicodeString name; 540 tz->getDisplayName(TRUE, TimeZone::LONG, 541 Locale.getDefault(), name); 542 errln("IllegalArgumentException not thrown by TimeZone::getDisplayName()");*/ 543 //} catch(IllegalArgumentException e) {} 544 } 545 546 /** 547 * @bug 4154537 548 * SimpleTimeZone::hasSameRules() doesn't work for zones with no DST 549 * and different DST parameters. 550 */ 551 void TimeZoneRegressionTest:: Test4154537() { 552 UErrorCode status = U_ZERO_ERROR; 553 // tz1 and tz2 have no DST and different rule parameters 554 SimpleTimeZone *tz1 = new SimpleTimeZone(0, "1", 0, 0, 0, 0, 2, 0, 0, 0, status); 555 SimpleTimeZone *tz2 = new SimpleTimeZone(0, "2", 1, 0, 0, 0, 3, 0, 0, 0, status); 556 // tza and tzA have the same rule params 557 SimpleTimeZone *tza = new SimpleTimeZone(0, "a", 0, 1, 0, 0, 3, 2, 0, 0, status); 558 SimpleTimeZone *tzA = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 3, 2, 0, 0, status); 559 // tzb differs from tza 560 SimpleTimeZone *tzb = new SimpleTimeZone(0, "b", 0, 1, 0, 0, 3, 1, 0, 0, status); 561 562 if(U_FAILURE(status)) 563 errln("Couldn't create TimeZones"); 564 565 if (tz1->useDaylightTime() || tz2->useDaylightTime() || 566 !tza->useDaylightTime() || !tzA->useDaylightTime() || 567 !tzb->useDaylightTime()) { 568 errln("Test is broken -- rewrite it"); 569 } 570 if (!tza->hasSameRules(*tzA) || tza->hasSameRules(*tzb)) { 571 errln("Fail: hasSameRules() broken for zones with rules"); 572 } 573 if (!tz1->hasSameRules(*tz2)) { 574 errln("Fail: hasSameRules() returns false for zones without rules"); 575 //errln("zone 1 = " + tz1); 576 //errln("zone 2 = " + tz2); 577 } 578 579 delete tz1; 580 delete tz2; 581 delete tza; 582 delete tzA; 583 delete tzb; 584 } 585 586 /** 587 * @bug 4154542 588 * SimpleTimeZOne constructors, setStartRule(), and setEndRule() don't 589 * check for out-of-range arguments. 590 */ 591 void TimeZoneRegressionTest:: Test4154542() 592 { 593 const int32_t GOOD = 1; 594 const int32_t BAD = 0; 595 596 const int32_t GOOD_MONTH = UCAL_JANUARY; 597 const int32_t GOOD_DAY = 1; 598 const int32_t GOOD_DAY_OF_WEEK = UCAL_SUNDAY; 599 const int32_t GOOD_TIME = 0; 600 601 int32_t DATA [] = { 602 GOOD, INT32_MIN, 0, INT32_MAX, INT32_MIN, 603 GOOD, UCAL_JANUARY, -5, UCAL_SUNDAY, 0, 604 GOOD, UCAL_DECEMBER, 5, UCAL_SATURDAY, 24*60*60*1000, 605 BAD, UCAL_DECEMBER, 5, UCAL_SATURDAY, 24*60*60*1000+1, 606 BAD, UCAL_DECEMBER, 5, UCAL_SATURDAY, -1, 607 BAD, UCAL_JANUARY, -6, UCAL_SUNDAY, 0, 608 BAD, UCAL_DECEMBER, 6, UCAL_SATURDAY, 24*60*60*1000, 609 GOOD, UCAL_DECEMBER, 1, 0, 0, 610 GOOD, UCAL_DECEMBER, 31, 0, 0, 611 BAD, UCAL_APRIL, 31, 0, 0, 612 BAD, UCAL_DECEMBER, 32, 0, 0, 613 BAD, UCAL_JANUARY-1, 1, UCAL_SUNDAY, 0, 614 BAD, UCAL_DECEMBER+1, 1, UCAL_SUNDAY, 0, 615 GOOD, UCAL_DECEMBER, 31, -UCAL_SUNDAY, 0, 616 GOOD, UCAL_DECEMBER, 31, -UCAL_SATURDAY, 0, 617 BAD, UCAL_DECEMBER, 32, -UCAL_SATURDAY, 0, 618 BAD, UCAL_DECEMBER, -32, -UCAL_SATURDAY, 0, 619 BAD, UCAL_DECEMBER, 31, -UCAL_SATURDAY-1, 0, 620 }; 621 SimpleTimeZone *zone = new SimpleTimeZone(0, "Z"); 622 for (int32_t i=0; i < 18*5; i+=5) { 623 UBool shouldBeGood = (DATA[i] == GOOD); 624 int32_t month = DATA[i+1]; 625 int32_t day = DATA[i+2]; 626 int32_t dayOfWeek = DATA[i+3]; 627 int32_t time = DATA[i+4]; 628 629 UErrorCode status = U_ZERO_ERROR; 630 631 //Exception ex = null; 632 //try { 633 zone->setStartRule(month, day, dayOfWeek, time, status); 634 //} catch (IllegalArgumentException e) { 635 // ex = e; 636 //} 637 if (U_SUCCESS(status) != shouldBeGood) { 638 errln(UnicodeString("setStartRule(month=") + month + ", day=" + day + 639 ", dayOfWeek=" + dayOfWeek + ", time=" + time + 640 (shouldBeGood ? (") should work") 641 : ") should fail but doesn't")); 642 } 643 644 //ex = null; 645 //try { 646 status = U_ZERO_ERROR; 647 zone->setEndRule(month, day, dayOfWeek, time, status); 648 //} catch (IllegalArgumentException e) { 649 // ex = e; 650 //} 651 if (U_SUCCESS(status) != shouldBeGood) { 652 errln(UnicodeString("setEndRule(month=") + month + ", day=" + day + 653 ", dayOfWeek=" + dayOfWeek + ", time=" + time + 654 (shouldBeGood ? (") should work") 655 : ") should fail but doesn't")); 656 } 657 658 //ex = null; 659 //try { 660 // {sfb} need to look into ctor problems! (UErrorCode vs. dst signature confusion) 661 status = U_ZERO_ERROR; 662 SimpleTimeZone *temp = new SimpleTimeZone(0, "Z", 663 (int8_t)month, (int8_t)day, (int8_t)dayOfWeek, time, 664 (int8_t)GOOD_MONTH, (int8_t)GOOD_DAY, (int8_t)GOOD_DAY_OF_WEEK, 665 GOOD_TIME,status); 666 //} catch (IllegalArgumentException e) { 667 // ex = e; 668 //} 669 if (U_SUCCESS(status) != shouldBeGood) { 670 errln(UnicodeString("SimpleTimeZone(month=") + month + ", day=" + day + 671 ", dayOfWeek=" + dayOfWeek + ", time=" + time + 672 (shouldBeGood ? (", <end>) should work")// + ex) 673 : ", <end>) should fail but doesn't")); 674 } 675 676 delete temp; 677 //ex = null; 678 //try { 679 status = U_ZERO_ERROR; 680 temp = new SimpleTimeZone(0, "Z", 681 (int8_t)GOOD_MONTH, (int8_t)GOOD_DAY, (int8_t)GOOD_DAY_OF_WEEK, 682 GOOD_TIME, 683 (int8_t)month, (int8_t)day, (int8_t)dayOfWeek, time,status); 684 //} catch (IllegalArgumentException e) { 685 // ex = e; 686 //} 687 if (U_SUCCESS(status) != shouldBeGood) { 688 errln(UnicodeString("SimpleTimeZone(<start>, month=") + month + ", day=" + day + 689 ", dayOfWeek=" + dayOfWeek + ", time=" + time + 690 (shouldBeGood ? (") should work")// + ex) 691 : ") should fail but doesn't")); 692 } 693 delete temp; 694 } 695 delete zone; 696 } 697 698 699 /** 700 * @bug 4154525 701 * SimpleTimeZone accepts illegal DST savings values. These values 702 * must be non-zero. There is no upper limit at this time. 703 */ 704 void 705 TimeZoneRegressionTest::Test4154525() 706 { 707 const int32_t GOOD = 1, BAD = 0; 708 709 int32_t DATA [] = { 710 1, GOOD, 711 0, BAD, 712 -1, BAD, 713 60*60*1000, GOOD, 714 INT32_MIN, BAD, 715 // Integer.MAX_VALUE, ?, // no upper limit on DST savings at this time 716 }; 717 718 UErrorCode status = U_ZERO_ERROR; 719 for(int32_t i = 0; i < 10; i+=2) { 720 int32_t savings = DATA[i]; 721 UBool valid = DATA[i+1] == GOOD; 722 UnicodeString method; 723 for(int32_t j=0; j < 2; ++j) { 724 SimpleTimeZone *z=NULL; 725 switch (j) { 726 case 0: 727 method = "constructor"; 728 z = new SimpleTimeZone(0, "id", 729 UCAL_JANUARY, 1, 0, 0, 730 UCAL_MARCH, 1, 0, 0, 731 savings, status); // <- what we're interested in 732 break; 733 case 1: 734 method = "setDSTSavings()"; 735 z = new SimpleTimeZone(0, "GMT"); 736 z->setDSTSavings(savings, status); 737 break; 738 } 739 740 if(U_FAILURE(status)) { 741 if(valid) { 742 errln(UnicodeString("Fail: DST savings of ") + savings + " to " + method + " gave " + u_errorName(status)); 743 } 744 else { 745 logln(UnicodeString("Pass: DST savings of ") + savings + " to " + method + " gave " + u_errorName(status)); 746 } 747 } 748 else { 749 if(valid) { 750 logln(UnicodeString("Pass: DST savings of ") + savings + " accepted by " + method); 751 } 752 else { 753 errln(UnicodeString("Fail: DST savings of ") + savings + " accepted by " + method); 754 } 755 } 756 status = U_ZERO_ERROR; 757 delete z; 758 } 759 } 760 } 761 762 /** 763 * @bug 4154650 764 * SimpleTimeZone.getOffset accepts illegal arguments. 765 */ 766 void 767 TimeZoneRegressionTest::Test4154650() 768 { 769 const int32_t GOOD = 1, BAD = 0; 770 const int32_t GOOD_ERA = GregorianCalendar::AD, GOOD_YEAR = 1998, GOOD_MONTH = UCAL_AUGUST; 771 const int32_t GOOD_DAY = 2, GOOD_DOW = UCAL_SUNDAY, GOOD_TIME = 16*3600000; 772 773 int32_t DATA []= { 774 GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, 775 776 GOOD, GregorianCalendar::BC, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, 777 GOOD, GregorianCalendar::AD, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, 778 BAD, GregorianCalendar::BC-1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, 779 BAD, GregorianCalendar::AD+1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, 780 781 GOOD, GOOD_ERA, GOOD_YEAR, UCAL_JANUARY, GOOD_DAY, GOOD_DOW, GOOD_TIME, 782 GOOD, GOOD_ERA, GOOD_YEAR, UCAL_DECEMBER, GOOD_DAY, GOOD_DOW, GOOD_TIME, 783 BAD, GOOD_ERA, GOOD_YEAR, UCAL_JANUARY-1, GOOD_DAY, GOOD_DOW, GOOD_TIME, 784 BAD, GOOD_ERA, GOOD_YEAR, UCAL_DECEMBER+1, GOOD_DAY, GOOD_DOW, GOOD_TIME, 785 786 GOOD, GOOD_ERA, GOOD_YEAR, UCAL_JANUARY, 1, GOOD_DOW, GOOD_TIME, 787 GOOD, GOOD_ERA, GOOD_YEAR, UCAL_JANUARY, 31, GOOD_DOW, GOOD_TIME, 788 BAD, GOOD_ERA, GOOD_YEAR, UCAL_JANUARY, 0, GOOD_DOW, GOOD_TIME, 789 BAD, GOOD_ERA, GOOD_YEAR, UCAL_JANUARY, 32, GOOD_DOW, GOOD_TIME, 790 791 GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, UCAL_SUNDAY, GOOD_TIME, 792 GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, UCAL_SATURDAY, GOOD_TIME, 793 BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, UCAL_SUNDAY-1, GOOD_TIME, 794 BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, UCAL_SATURDAY+1, GOOD_TIME, 795 796 GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 0, 797 GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000-1, 798 BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, -1, 799 BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000, 800 }; 801 802 int32_t dataLen = (int32_t)(sizeof(DATA) / sizeof(DATA[0])); 803 804 UErrorCode status = U_ZERO_ERROR; 805 TimeZone *tz = TimeZone::createDefault(); 806 for(int32_t i = 0; i < dataLen; i += 7) { 807 UBool good = DATA[i] == GOOD; 808 //IllegalArgumentException e = null; 809 //try { 810 /*int32_t offset = */ 811 tz->getOffset((uint8_t)DATA[i+1], DATA[i+2], DATA[i+3], 812 DATA[i+4], (uint8_t)DATA[i+5], DATA[i+6], status); 813 //} catch (IllegalArgumentException ex) { 814 // e = ex; 815 //} 816 if(good != U_SUCCESS(status)) { 817 UnicodeString errMsg; 818 if (good) { 819 errMsg = (UnicodeString(") threw ") + u_errorName(status)); 820 } 821 else { 822 errMsg = UnicodeString(") accepts invalid args", ""); 823 } 824 errln(UnicodeString("Fail: getOffset(") + 825 DATA[i+1] + ", " + DATA[i+2] + ", " + DATA[i+3] + ", " + 826 DATA[i+4] + ", " + DATA[i+5] + ", " + DATA[i+6] + 827 errMsg); 828 } 829 status = U_ZERO_ERROR; // reset 830 } 831 delete tz; 832 } 833 834 /** 835 * @bug 4162593 836 * TimeZone broken at midnight. The TimeZone code fails to handle 837 * transitions at midnight correctly. 838 */ 839 void 840 TimeZoneRegressionTest::Test4162593() 841 { 842 UErrorCode status = U_ZERO_ERROR; 843 SimpleDateFormat *fmt = new SimpleDateFormat("z", Locale::getUS(), status); 844 if(U_FAILURE(status)) { 845 dataerrln("Error creating calendar %s", u_errorName(status)); 846 delete fmt; 847 return; 848 } 849 const int32_t ONE_HOUR = 60*60*1000; 850 851 SimpleTimeZone *asuncion = new SimpleTimeZone(-4*ONE_HOUR, "America/Asuncion" /*PY%sT*/, 852 UCAL_OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR, 853 UCAL_MARCH, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR, status); 854 855 /* Zone 856 * Starting time 857 * Transition expected between start+1H and start+2H 858 */ 859 TimeZone *DATA_TZ [] = { 860 0, 0, 0 }; 861 862 int32_t DATA_INT [] [5] = { 863 // These years must be AFTER the Gregorian cutover 864 {1998, UCAL_SEPTEMBER, 30, 22, 0}, 865 {2000, UCAL_FEBRUARY, 28, 22, 0}, 866 {2000, UCAL_FEBRUARY, 29, 22, 0}, 867 }; 868 869 UBool DATA_BOOL [] = { 870 TRUE, 871 FALSE, 872 TRUE, 873 }; 874 875 UnicodeString zone [4];// = new String[4]; 876 DATA_TZ[0] = 877 new SimpleTimeZone(2*ONE_HOUR, "Asia/Damascus" /*EE%sT*/, 878 UCAL_APRIL, 1, 0 /*DOM*/, 0*ONE_HOUR, 879 UCAL_OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR, status); 880 DATA_TZ[1] = asuncion; DATA_TZ[2] = asuncion; 881 882 for(int32_t j = 0; j < 3; j++) { 883 TimeZone *tz = (TimeZone*)DATA_TZ[j]; 884 TimeZone::setDefault(*tz); 885 fmt->setTimeZone(*tz); 886 887 // Must construct the Date object AFTER setting the default zone 888 int32_t *p = (int32_t*)DATA_INT[j]; 889 UDate d = CalendarRegressionTest::makeDate(p[0], p[1], p[2], p[3], p[4]); 890 UBool transitionExpected = DATA_BOOL[j]; 891 892 UnicodeString temp; 893 logln(tz->getID(temp) + ":"); 894 for (int32_t i = 0; i < 4; ++i) { 895 FieldPosition pos(0); 896 zone[i].remove(); 897 zone[i] = fmt->format(d+ i*ONE_HOUR, zone[i], pos); 898 logln(UnicodeString("") + i + ": " + d + " / " + zone[i]); 899 //d += (double) ONE_HOUR; 900 } 901 if(zone[0] == zone[1] && 902 (zone[1] == zone[2]) != transitionExpected && 903 zone[2] == zone[3]) { 904 logln(UnicodeString("Ok: transition ") + transitionExpected); 905 } 906 else { 907 errln("Fail: boundary transition incorrect"); 908 } 909 } 910 delete fmt; 911 delete asuncion; 912 delete DATA_TZ[0]; 913 } 914 915 /** 916 * getDisplayName doesn't work with unusual savings/offsets. 917 */ 918 void TimeZoneRegressionTest::Test4176686() { 919 // Construct a zone that does not observe DST but 920 // that does have a DST savings (which should be ignored). 921 UErrorCode status = U_ZERO_ERROR; 922 int32_t offset = 90 * 60000; // 1:30 923 SimpleTimeZone* z1 = new SimpleTimeZone(offset, "_std_zone_"); 924 z1->setDSTSavings(45 * 60000, status); // 0:45 925 926 // Construct a zone that observes DST for the first 6 months. 927 SimpleTimeZone* z2 = new SimpleTimeZone(offset, "_dst_zone_"); 928 z2->setDSTSavings(45 * 60000, status); // 0:45 929 z2->setStartRule(UCAL_JANUARY, 1, 0, status); 930 z2->setEndRule(UCAL_JULY, 1, 0, status); 931 932 // Also check DateFormat 933 DateFormat* fmt1 = new SimpleDateFormat(UnicodeString("z"), status); 934 if (U_FAILURE(status)) { 935 dataerrln("Failure trying to construct: %s", u_errorName(status)); 936 return; 937 } 938 fmt1->setTimeZone(*z1); // Format uses standard zone 939 DateFormat* fmt2 = new SimpleDateFormat(UnicodeString("z"), status); 940 if(!assertSuccess("trying to construct", status))return; 941 fmt2->setTimeZone(*z2); // Format uses DST zone 942 Calendar* tempcal = Calendar::createInstance(status); 943 tempcal->clear(); 944 tempcal->set(1970, UCAL_FEBRUARY, 1); 945 UDate dst = tempcal->getTime(status); // Time in DST 946 tempcal->set(1970, UCAL_AUGUST, 1); 947 UDate std = tempcal->getTime(status); // Time in standard 948 949 // Description, Result, Expected Result 950 UnicodeString a,b,c,d,e,f,g,h,i,j,k,l; 951 UnicodeString DATA[] = { 952 "z1->getDisplayName(false, SHORT)/std zone", 953 z1->getDisplayName(FALSE, TimeZone::SHORT, a), "GMT+01:30", 954 "z1->getDisplayName(false, LONG)/std zone", 955 z1->getDisplayName(FALSE, TimeZone::LONG, b), "GMT+01:30", 956 "z1->getDisplayName(true, SHORT)/std zone", 957 z1->getDisplayName(TRUE, TimeZone::SHORT, c), "GMT+01:30", 958 "z1->getDisplayName(true, LONG)/std zone", 959 z1->getDisplayName(TRUE, TimeZone::LONG, d ), "GMT+01:30", 960 "z2->getDisplayName(false, SHORT)/dst zone", 961 z2->getDisplayName(FALSE, TimeZone::SHORT, e), "GMT+01:30", 962 "z2->getDisplayName(false, LONG)/dst zone", 963 z2->getDisplayName(FALSE, TimeZone::LONG, f ), "GMT+01:30", 964 "z2->getDisplayName(true, SHORT)/dst zone", 965 z2->getDisplayName(TRUE, TimeZone::SHORT, g), "GMT+02:15", 966 "z2->getDisplayName(true, LONG)/dst zone", 967 z2->getDisplayName(TRUE, TimeZone::LONG, h ), "GMT+02:15", 968 "DateFormat.format(std)/std zone", fmt1->format(std, i), "GMT+01:30", 969 "DateFormat.format(dst)/std zone", fmt1->format(dst, j), "GMT+01:30", 970 "DateFormat.format(std)/dst zone", fmt2->format(std, k), "GMT+01:30", 971 "DateFormat.format(dst)/dst zone", fmt2->format(dst, l), "GMT+02:15", 972 }; 973 974 for (int32_t idx=0; idx<(int32_t)ARRAY_LENGTH(DATA); idx+=3) { 975 if (DATA[idx+1]!=(DATA[idx+2])) { 976 errln("FAIL: " + DATA[idx] + " -> " + DATA[idx+1] + ", exp " + DATA[idx+2]); 977 } 978 } 979 delete z1; 980 delete z2; 981 delete fmt1; 982 delete fmt2; 983 delete tempcal; 984 } 985 986 /** 987 * Make sure setStartRule and setEndRule set the DST savings to nonzero 988 * if it was zero. 989 */ 990 void TimeZoneRegressionTest::TestJ186() { 991 UErrorCode status = U_ZERO_ERROR; 992 // NOTE: Setting the DST savings to zero is illegal, so we 993 // are limited in the testing we can do here. This is why 994 // lines marked //~ are commented out. 995 SimpleTimeZone z(0, "ID"); 996 //~z.setDSTSavings(0, status); // Must do this! 997 z.setStartRule(UCAL_FEBRUARY, 1, UCAL_SUNDAY, 0, status); 998 failure(status, "setStartRule()"); 999 if (z.useDaylightTime()) { 1000 errln("Fail: useDaylightTime true with start rule only"); 1001 } 1002 //~if (z.getDSTSavings() != 0) { 1003 //~ errln("Fail: dst savings != 0 with start rule only"); 1004 //~} 1005 z.setEndRule(UCAL_MARCH, -1, UCAL_SUNDAY, 0, status); 1006 failure(status, "setStartRule()"); 1007 if (!z.useDaylightTime()) { 1008 errln("Fail: useDaylightTime false with rules set"); 1009 } 1010 if (z.getDSTSavings() == 0) { 1011 errln("Fail: dst savings == 0 with rules set"); 1012 } 1013 } 1014 1015 /** 1016 * Test to see if DateFormat understands zone equivalency groups. It 1017 * might seem that this should be a DateFormat test, but it's really a 1018 * TimeZone test -- the changes to DateFormat are minor. 1019 * 1020 * We use two known, stable zones that shouldn't change much over time 1021 * -- America/Vancouver and America/Los_Angeles. However, they MAY 1022 * change at some point -- if that happens, replace them with any two 1023 * zones in an equivalency group where one zone has localized name 1024 * data, and the other doesn't, in some locale. 1025 */ 1026 void TimeZoneRegressionTest::TestJ449() { 1027 UErrorCode status = U_ZERO_ERROR; 1028 UnicodeString str; 1029 1030 // Modify the following three as necessary. The two IDs must 1031 // specify two zones in the same equivalency group. One must have 1032 // locale data in 'loc'; the other must not. 1033 const char* idWithLocaleData = "America/Los_Angeles"; 1034 const char* idWithoutLocaleData = "US/Pacific"; 1035 const Locale loc("en", "", ""); 1036 1037 TimeZone *zoneWith = TimeZone::createTimeZone(idWithLocaleData); 1038 TimeZone *zoneWithout = TimeZone::createTimeZone(idWithoutLocaleData); 1039 // Make sure we got valid zones 1040 if (zoneWith->getID(str) != UnicodeString(idWithLocaleData) || 1041 zoneWithout->getID(str) != UnicodeString(idWithoutLocaleData)) { 1042 dataerrln(UnicodeString("Fail: Unable to create zones - wanted ") + idWithLocaleData + ", got " + zoneWith->getID(str) + ", and wanted " + idWithoutLocaleData + " but got " + zoneWithout->getID(str)); 1043 } else { 1044 GregorianCalendar calWith(*zoneWith, status); 1045 GregorianCalendar calWithout(*zoneWithout, status); 1046 SimpleDateFormat fmt("MMM d yyyy hh:mm a zzz", loc, status); 1047 if (U_FAILURE(status)) { 1048 errln("Fail: Unable to create GregorianCalendar/SimpleDateFormat"); 1049 } else { 1050 UDate date = 0; 1051 UnicodeString strWith, strWithout; 1052 fmt.setCalendar(calWith); 1053 fmt.format(date, strWith); 1054 fmt.setCalendar(calWithout); 1055 fmt.format(date, strWithout); 1056 if (strWith == strWithout) { 1057 logln((UnicodeString)"Ok: " + idWithLocaleData + " -> " + 1058 strWith + "; " + idWithoutLocaleData + " -> " + 1059 strWithout); 1060 } else { 1061 errln((UnicodeString)"FAIL: " + idWithLocaleData + " -> " + 1062 strWith + "; " + idWithoutLocaleData + " -> " + 1063 strWithout); 1064 } 1065 } 1066 } 1067 1068 delete zoneWith; 1069 delete zoneWithout; 1070 } 1071 1072 // test new API for JDK 1.2 8/31 putback 1073 void 1074 TimeZoneRegressionTest::TestJDK12API() 1075 { 1076 // TimeZone *pst = TimeZone::createTimeZone("PST"); 1077 // TimeZone *cst1 = TimeZone::createTimeZone("CST"); 1078 UErrorCode ec = U_ZERO_ERROR; 1079 //d,-28800,3,1,-1,120,w,9,-1,1,120,w,60 1080 TimeZone *pst = new SimpleTimeZone(-28800*U_MILLIS_PER_SECOND, 1081 "PST", 1082 3,1,-1,120*U_MILLIS_PER_MINUTE, 1083 SimpleTimeZone::WALL_TIME, 1084 9,-1,1,120*U_MILLIS_PER_MINUTE, 1085 SimpleTimeZone::WALL_TIME, 1086 60*U_MILLIS_PER_MINUTE,ec); 1087 //d,-21600,3,1,-1,120,w,9,-1,1,120,w,60 1088 TimeZone *cst1 = new SimpleTimeZone(-21600*U_MILLIS_PER_SECOND, 1089 "CST", 1090 3,1,-1,120*U_MILLIS_PER_MINUTE, 1091 SimpleTimeZone::WALL_TIME, 1092 9,-1,1,120*U_MILLIS_PER_MINUTE, 1093 SimpleTimeZone::WALL_TIME, 1094 60*U_MILLIS_PER_MINUTE,ec); 1095 if (U_FAILURE(ec)) { 1096 errln("FAIL: SimpleTimeZone constructor"); 1097 return; 1098 } 1099 1100 SimpleTimeZone *cst = dynamic_cast<SimpleTimeZone *>(cst1); 1101 1102 if(pst->hasSameRules(*cst)) { 1103 errln("FAILURE: PST and CST have same rules"); 1104 } 1105 1106 UErrorCode status = U_ZERO_ERROR; 1107 int32_t offset1 = pst->getOffset(1, 1108 1997, UCAL_OCTOBER, 26, UCAL_SUNDAY, (2*60*60*1000), status); 1109 failure(status, "getOffset() failed"); 1110 1111 1112 int32_t offset2 = cst->getOffset(1, 1113 1997, UCAL_OCTOBER, 26, UCAL_SUNDAY, (2*60*60*1000), 31, status); 1114 failure(status, "getOffset() failed"); 1115 1116 if(offset1 == offset2) 1117 errln("FAILURE: Sunday Oct. 26 1997 2:00 has same offset for PST and CST"); 1118 1119 // verify error checking 1120 pst->getOffset(1, 1121 1997, UCAL_FIELD_COUNT+1, 26, UCAL_SUNDAY, (2*60*60*1000), status); 1122 if(U_SUCCESS(status)) 1123 errln("FAILURE: getOffset() succeeded with -1 for month"); 1124 1125 status = U_ZERO_ERROR; 1126 cst->setDSTSavings(60*60*1000, status); 1127 failure(status, "setDSTSavings() failed"); 1128 1129 int32_t savings = cst->getDSTSavings(); 1130 if(savings != 60*60*1000) { 1131 errln("setDSTSavings() failed"); 1132 } 1133 1134 delete pst; 1135 delete cst; 1136 } 1137 /** 1138 * SimpleTimeZone allows invalid DOM values. 1139 */ 1140 void TimeZoneRegressionTest::Test4184229() { 1141 SimpleTimeZone* zone = NULL; 1142 UErrorCode status = U_ZERO_ERROR; 1143 zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0, status); 1144 if(U_SUCCESS(status)){ 1145 errln("Failed. No exception has been thrown for DOM -1 startDay"); 1146 }else{ 1147 logln("(a) " + UnicodeString( u_errorName(status))); 1148 } 1149 status = U_ZERO_ERROR; 1150 delete zone; 1151 1152 zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0, status); 1153 if(U_SUCCESS(status)){ 1154 errln("Failed. No exception has been thrown for DOM -1 endDay"); 1155 }else{ 1156 logln("(b) " + UnicodeString(u_errorName(status))); 1157 } 1158 status = U_ZERO_ERROR; 1159 delete zone; 1160 1161 zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 1000, status); 1162 if(U_SUCCESS(status)){ 1163 errln("Failed. No exception has been thrown for DOM -1 startDay+savings"); 1164 }else{ 1165 logln("(c) " + UnicodeString(u_errorName(status))); 1166 } 1167 status = U_ZERO_ERROR; 1168 delete zone; 1169 zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0, 1000, status); 1170 if(U_SUCCESS(status)){ 1171 errln("Failed. No exception has been thrown for DOM -1 endDay+ savings"); 1172 }else{ 1173 logln("(d) " + UnicodeString(u_errorName(status))); 1174 } 1175 status = U_ZERO_ERROR; 1176 delete zone; 1177 // Make a valid constructor call for subsequent tests. 1178 zone = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 0, 1, 0, 0, status); 1179 1180 zone->setStartRule(0, -1, 0, 0, status); 1181 if(U_SUCCESS(status)){ 1182 errln("Failed. No exception has been thrown for DOM -1 setStartRule +savings"); 1183 } else{ 1184 logln("(e) " + UnicodeString(u_errorName(status))); 1185 } 1186 zone->setStartRule(0, -1, 0, status); 1187 if(U_SUCCESS(status)){ 1188 errln("Failed. No exception has been thrown for DOM -1 setStartRule"); 1189 } else{ 1190 logln("(f) " + UnicodeString(u_errorName(status))); 1191 } 1192 1193 zone->setEndRule(0, -1, 0, 0, status); 1194 if(U_SUCCESS(status)){ 1195 errln("Failed. No exception has been thrown for DOM -1 setEndRule+savings"); 1196 } else{ 1197 logln("(g) " + UnicodeString(u_errorName(status))); 1198 } 1199 1200 zone->setEndRule(0, -1, 0, status); 1201 if(U_SUCCESS(status)){ 1202 errln("Failed. No exception has been thrown for DOM -1 setEndRule"); 1203 } else{ 1204 logln("(h) " + UnicodeString(u_errorName(status))); 1205 } 1206 delete zone; 1207 } 1208 1209 #endif /* #if !UCONFIG_NO_FORMATTING */ 1210