2 ******************************************************************************* 
   3 * Copyright (C) 2007-2016, International Business Machines Corporation and 
   4 * others. All Rights Reserved. 
   5 ******************************************************************************* 
   8 #include "unicode/utypes.h" 
  10 #if !UCONFIG_NO_FORMATTING 
  12 #include "unicode/dtrule.h" 
  13 #include "unicode/tzrule.h" 
  14 #include "unicode/rbtz.h" 
  15 #include "unicode/simpletz.h" 
  16 #include "unicode/tzrule.h" 
  17 #include "unicode/calendar.h" 
  18 #include "unicode/gregocal.h" 
  19 #include "unicode/ucal.h" 
  20 #include "unicode/unistr.h" 
  21 #include "unicode/ustring.h" 
  22 #include "unicode/tztrans.h" 
  23 #include "unicode/vtzone.h" 
  30 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break 
  31 #define HOUR (60*60*1000) 
  33 static const char *const TESTZIDS
[] = { 
  36         "America/Los_Angeles", 
  37         "America/Indiana/Indianapolis", 
  49 static UBool 
hasEquivalentTransitions(/*const*/ BasicTimeZone
& tz1
, /*const*/BasicTimeZone
& tz2
, 
  50                                         UDate start
, UDate end
, 
  51                                         UBool ignoreDstAmount
, int32_t maxTransitionTimeDelta
, 
  54 class TestZIDEnumeration 
: public StringEnumeration 
{ 
  56     TestZIDEnumeration(UBool all 
= FALSE
); 
  57     ~TestZIDEnumeration(); 
  59     virtual int32_t count(UErrorCode
& /*status*/) const { 
  62     virtual const UnicodeString 
*snext(UErrorCode
& status
); 
  63     virtual void reset(UErrorCode
& status
); 
  64     static inline UClassID 
getStaticClassID() { 
  65         return (UClassID
)&fgClassID
; 
  67     virtual UClassID 
getDynamicClassID() const { 
  68         return getStaticClassID(); 
  71     static const char fgClassID
; 
  74     StringEnumeration   
*tzenum
; 
  77 const char TestZIDEnumeration::fgClassID 
= 0; 
  79 TestZIDEnumeration::TestZIDEnumeration(UBool all
) 
  81     UErrorCode status 
= U_ZERO_ERROR
; 
  83         tzenum 
= TimeZone::createEnumeration(); 
  84         len 
= tzenum
->count(status
); 
  87         len 
= UPRV_LENGTHOF(TESTZIDS
); 
  91 TestZIDEnumeration::~TestZIDEnumeration() { 
  98 TestZIDEnumeration::snext(UErrorCode
& status
) { 
 100         return tzenum
->snext(status
); 
 101     } else if (U_SUCCESS(status
) && idx 
< len
) { 
 102         unistr 
= UnicodeString(TESTZIDS
[idx
++], ""); 
 109 TestZIDEnumeration::reset(UErrorCode
& status
) { 
 110     if (tzenum 
!= NULL
) { 
 111         tzenum
->reset(status
); 
 118 void TimeZoneRuleTest::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* /*par*/ ) 
 121         logln("TestSuite TestTimeZoneRule"); 
 124         CASE(0, TestSimpleRuleBasedTimeZone
); 
 125         CASE(1, TestHistoricalRuleBasedTimeZone
); 
 126         CASE(2, TestOlsonTransition
); 
 127         CASE(3, TestRBTZTransition
); 
 128         CASE(4, TestHasEquivalentTransitions
); 
 129         CASE(5, TestVTimeZoneRoundTrip
); 
 130         CASE(6, TestVTimeZoneRoundTripPartial
); 
 131         CASE(7, TestVTimeZoneSimpleWrite
); 
 132         CASE(8, TestVTimeZoneHeaderProps
); 
 133         CASE(9, TestGetSimpleRules
); 
 134         CASE(10, TestTimeZoneRuleCoverage
); 
 135         CASE(11, TestSimpleTimeZoneCoverage
); 
 136         CASE(12, TestVTimeZoneCoverage
); 
 137         CASE(13, TestVTimeZoneParse
); 
 140         CASE(16, TestVTimeZoneWrapper
); 
 142         default: name 
= ""; break; 
 147  * Compare SimpleTimeZone with equivalent RBTZ 
 150 TimeZoneRuleTest::TestSimpleRuleBasedTimeZone(void) { 
 151     UErrorCode status 
= U_ZERO_ERROR
; 
 152     SimpleTimeZone 
stz(-1*HOUR
, "TestSTZ", 
 153         UCAL_SEPTEMBER
, -30, -UCAL_SATURDAY
, 1*HOUR
, SimpleTimeZone::WALL_TIME
, 
 154         UCAL_FEBRUARY
, 2, UCAL_SUNDAY
, 1*HOUR
, SimpleTimeZone::WALL_TIME
, 
 156     if (U_FAILURE(status
)) { 
 157         errln("FAIL: Couldn't create SimpleTimezone."); 
 161     AnnualTimeZoneRule 
*atzr
; 
 162     int32_t STARTYEAR 
= 2000; 
 164     InitialTimeZoneRule 
*ir 
= new InitialTimeZoneRule( 
 165         "RBTZ_Initial", // Initial time Name 
 166         -1*HOUR
,        // Raw offset 
 167         1*HOUR
);        // DST saving amount 
 170     RuleBasedTimeZone 
*rbtz1 
= new RuleBasedTimeZone("RBTZ1", ir
->clone()); 
 171     dtr 
= new DateTimeRule(UCAL_SEPTEMBER
, 30, UCAL_SATURDAY
, FALSE
, 
 172         1*HOUR
, DateTimeRule::WALL_TIME
); // SUN<=30 in September, at 1AM wall time 
 173     atzr 
= new AnnualTimeZoneRule("RBTZ_DST1", 
 174         -1*HOUR 
/*rawOffset*/, 1*HOUR 
/*dstSavings*/, dtr
, 
 175         STARTYEAR
, AnnualTimeZoneRule::MAX_YEAR
); 
 176     rbtz1
->addTransitionRule(atzr
, status
); 
 177     if (U_FAILURE(status
)) { 
 178         errln("FAIL: couldn't add AnnualTimeZoneRule 1-1."); 
 180     dtr 
= new DateTimeRule(UCAL_FEBRUARY
, 2, UCAL_SUNDAY
, 
 181         1*HOUR
, DateTimeRule::WALL_TIME
);  // 2nd Sunday in February, at 1AM wall time 
 182     atzr 
= new AnnualTimeZoneRule("RBTZ_STD1", 
 183         -1*HOUR 
/*rawOffset*/, 0 /*dstSavings*/, dtr
, 
 184         STARTYEAR
, AnnualTimeZoneRule::MAX_YEAR
); 
 185     rbtz1
->addTransitionRule(atzr
, status
); 
 186     if (U_FAILURE(status
)) { 
 187         errln("FAIL: couldn't add AnnualTimeZoneRule 1-2."); 
 189     rbtz1
->complete(status
); 
 190     if (U_FAILURE(status
)) { 
 191         errln("FAIL: couldn't complete RBTZ 1."); 
 194     // Equivalent, but different date rule type 
 195     RuleBasedTimeZone 
*rbtz2 
= new RuleBasedTimeZone("RBTZ2", ir
->clone()); 
 196     dtr 
= new DateTimeRule(UCAL_SEPTEMBER
, -1, UCAL_SATURDAY
, 
 197         1*HOUR
, DateTimeRule::WALL_TIME
); // Last Sunday in September at 1AM wall time 
 198     atzr 
= new AnnualTimeZoneRule("RBTZ_DST2", -1*HOUR
, 1*HOUR
, dtr
, STARTYEAR
, AnnualTimeZoneRule::MAX_YEAR
); 
 199     rbtz2
->addTransitionRule(atzr
, status
); 
 200     if (U_FAILURE(status
)) { 
 201         errln("FAIL: couldn't add AnnualTimeZoneRule 2-1."); 
 203     dtr 
= new DateTimeRule(UCAL_FEBRUARY
, 8, UCAL_SUNDAY
, true, 
 204         1*HOUR
, DateTimeRule::WALL_TIME
); // SUN>=8 in February, at 1AM wall time 
 205     atzr 
= new AnnualTimeZoneRule("RBTZ_STD2", -1*HOUR
, 0, dtr
, STARTYEAR
, AnnualTimeZoneRule::MAX_YEAR
); 
 206     rbtz2
->addTransitionRule(atzr
, status
); 
 207     if (U_FAILURE(status
)) { 
 208         errln("FAIL: couldn't add AnnualTimeZoneRule 2-2."); 
 210     rbtz2
->complete(status
); 
 211     if (U_FAILURE(status
)) { 
 212         errln("FAIL: couldn't complete RBTZ 2"); 
 215     // Equivalent, but different time rule type 
 216     RuleBasedTimeZone 
*rbtz3 
= new RuleBasedTimeZone("RBTZ3", ir
->clone()); 
 217     dtr 
= new DateTimeRule(UCAL_SEPTEMBER
, 30, UCAL_SATURDAY
, false, 
 218         2*HOUR
, DateTimeRule::UTC_TIME
); 
 219     atzr 
= new AnnualTimeZoneRule("RBTZ_DST3", -1*HOUR
, 1*HOUR
, dtr
, STARTYEAR
, AnnualTimeZoneRule::MAX_YEAR
); 
 220     rbtz3
->addTransitionRule(atzr
, status
); 
 221     if (U_FAILURE(status
)) { 
 222         errln("FAIL: couldn't add AnnualTimeZoneRule 3-1."); 
 224     dtr 
= new DateTimeRule(UCAL_FEBRUARY
, 2, UCAL_SUNDAY
, 
 225         0*HOUR
, DateTimeRule::STANDARD_TIME
); 
 226     atzr 
= new AnnualTimeZoneRule("RBTZ_STD3", -1*HOUR
, 0, dtr
, STARTYEAR
, AnnualTimeZoneRule::MAX_YEAR
); 
 227     rbtz3
->addTransitionRule(atzr
, status
); 
 228     if (U_FAILURE(status
)) { 
 229         errln("FAIL: couldn't add AnnualTimeZoneRule 3-2."); 
 231     rbtz3
->complete(status
); 
 232     if (U_FAILURE(status
)) { 
 233         errln("FAIL: couldn't complete RBTZ 3"); 
 236     // Check equivalency for 10 years 
 237     UDate start 
= getUTCMillis(STARTYEAR
, UCAL_JANUARY
, 1); 
 238     UDate until 
= getUTCMillis(STARTYEAR 
+ 10, UCAL_JANUARY
, 1); 
 240     if (!(stz
.hasEquivalentTransitions(*rbtz1
, start
, until
, TRUE
, status
))) { 
 241         errln("FAIL: rbtz1 must be equivalent to the SimpleTimeZone in the time range."); 
 243     if (U_FAILURE(status
)) { 
 244         errln("FAIL: error returned from hasEquivalentTransitions"); 
 246     if (!(stz
.hasEquivalentTransitions(*rbtz2
, start
, until
, TRUE
, status
))) { 
 247         errln("FAIL: rbtz2 must be equivalent to the SimpleTimeZone in the time range."); 
 249     if (U_FAILURE(status
)) { 
 250         errln("FAIL: error returned from hasEquivalentTransitions"); 
 252     if (!(stz
.hasEquivalentTransitions(*rbtz3
, start
, until
, TRUE
, status
))) { 
 253         errln("FAIL: rbtz3 must be equivalent to the SimpleTimeZone in the time range."); 
 255     if (U_FAILURE(status
)) { 
 256         errln("FAIL: error returned from hasEquivalentTransitions"); 
 260     if (rbtz1
->hasSameRules(*rbtz2
)) { 
 261         errln("FAIL: rbtz1 and rbtz2 have different rules, but returned true."); 
 263     if (rbtz1
->hasSameRules(*rbtz3
)) { 
 264         errln("FAIL: rbtz1 and rbtz3 have different rules, but returned true."); 
 266     RuleBasedTimeZone 
*rbtz1c 
= (RuleBasedTimeZone
*)rbtz1
->clone(); 
 267     if (!rbtz1
->hasSameRules(*rbtz1c
)) { 
 268         errln("FAIL: Cloned RuleBasedTimeZone must have the same rules with the original."); 
 272     int32_t era
, year
, month
, dayOfMonth
, dayOfWeek
, millisInDay
; 
 274     int32_t offset
, dstSavings
; 
 277     GregorianCalendar 
*cal 
= new GregorianCalendar(status
); 
 278     if (U_FAILURE(status
)) { 
 279         dataerrln("FAIL: Could not create a Gregorian calendar instance.: %s", u_errorName(status
)); 
 286     cal
->setTimeZone(*rbtz1
); 
 290     cal
->set(UCAL_ERA
, GregorianCalendar::BC
); 
 291     cal
->set(1000, UCAL_JANUARY
, 1); 
 293     era 
= cal
->get(UCAL_ERA
, status
); 
 294     year 
= cal
->get(UCAL_YEAR
, status
); 
 295     month 
= cal
->get(UCAL_MONTH
, status
); 
 296     dayOfMonth 
= cal
->get(UCAL_DAY_OF_MONTH
, status
); 
 297     dayOfWeek 
= cal
->get(UCAL_DAY_OF_WEEK
, status
); 
 298     millisInDay 
= cal
->get(UCAL_MILLISECONDS_IN_DAY
, status
); 
 299     time 
= cal
->getTime(status
); 
 300     if (U_FAILURE(status
)) { 
 301         errln("FAIL: Could not get calendar field values."); 
 303     offset 
= rbtz1
->getOffset(era
, year
, month
, dayOfMonth
, dayOfWeek
, millisInDay
, status
); 
 304     if (U_FAILURE(status
)) { 
 305         errln("FAIL: getOffset(7 args) failed."); 
 308         errln(UnicodeString("FAIL: Invalid time zone offset: ") + offset 
+ " /expected: 0"); 
 310     dst 
= rbtz1
->inDaylightTime(time
, status
); 
 311     if (U_FAILURE(status
)) { 
 312         errln("FAIL: inDaylightTime failed."); 
 315         errln("FAIL: Invalid daylight saving time"); 
 317     rbtz1
->getOffset(time
, TRUE
, offset
, dstSavings
, status
); 
 318     if (U_FAILURE(status
)) { 
 319         errln("FAIL: getOffset(5 args) failed."); 
 321     if (offset 
!= -3600000) { 
 322         errln(UnicodeString("FAIL: Invalid time zone raw offset: ") + offset 
+ " /expected: -3600000"); 
 324     if (dstSavings 
!= 3600000) {             
 325         errln(UnicodeString("FAIL: Invalid DST amount: ") + dstSavings 
+ " /expected: 3600000"); 
 329     cal
->set(UCAL_ERA
, GregorianCalendar::AD
); 
 330     cal
->set(2000, UCAL_JULY
, 1); 
 332     era 
= cal
->get(UCAL_ERA
, status
); 
 333     year 
= cal
->get(UCAL_YEAR
, status
); 
 334     month 
= cal
->get(UCAL_MONTH
, status
); 
 335     dayOfMonth 
= cal
->get(UCAL_DAY_OF_MONTH
, status
); 
 336     dayOfWeek 
= cal
->get(UCAL_DAY_OF_WEEK
, status
); 
 337     millisInDay 
= cal
->get(UCAL_MILLISECONDS_IN_DAY
, status
); 
 338     time 
= cal
->getTime(status
); 
 339     if (U_FAILURE(status
)) { 
 340         errln("FAIL: Could not get calendar field values."); 
 342     offset 
= rbtz1
->getOffset(era
, year
, month
, dayOfMonth
, dayOfWeek
, millisInDay
, status
); 
 343     if (U_FAILURE(status
)) { 
 344         errln("FAIL: getOffset(7 args) failed."); 
 346     if (offset 
!= -3600000) { 
 347         errln((UnicodeString
)"FAIL: Invalid time zone offset: " + offset 
+ " /expected: -3600000"); 
 349     dst 
= rbtz1
->inDaylightTime(time
, status
); 
 350     if (U_FAILURE(status
)) { 
 351         errln("FAIL: inDaylightTime failed."); 
 354         errln("FAIL: Invalid daylight saving time"); 
 356     rbtz1
->getOffset(time
, TRUE
, offset
, dstSavings
, status
); 
 357     if (U_FAILURE(status
)) { 
 358         errln("FAIL: getOffset(5 args) failed."); 
 360     if (offset 
!= -3600000) { 
 361         errln((UnicodeString
)"FAIL: Invalid time zone raw offset: " + offset 
+ " /expected: -3600000"); 
 363     if (dstSavings 
!= 0) {             
 364         errln((UnicodeString
)"FAIL: Invalid DST amount: " + dstSavings 
+ " /expected: 0"); 
 368     offset 
= rbtz1
->getRawOffset(); 
 369     if (offset 
!= -1*HOUR
) { 
 370         errln((UnicodeString
)"FAIL: Invalid time zone raw offset returned by getRawOffset: " 
 371             + offset 
+ " /expected: -3600000"); 
 375     RuleBasedTimeZone 
rbtz0("RBTZ1", ir
->clone()); 
 376     if (rbtz0 
== *rbtz1 
|| !(rbtz0 
!= *rbtz1
)) { 
 377         errln("FAIL: RuleBasedTimeZone rbtz0 is not equal to rbtz1, but got wrong result"); 
 380     if (rbtz0 
!= *rbtz1 
|| !(rbtz0 
== *rbtz1
)) { 
 381         errln("FAIL: RuleBasedTimeZone rbtz0 is equal to rbtz1, but got wrong result"); 
 385     const int32_t RAW 
= -10*HOUR
; 
 386     rbtz0
.setRawOffset(RAW
); 
 387     if (rbtz0
.getRawOffset() != RAW
) { 
 388         logln("setRawOffset is implemented in RuleBasedTimeZone"); 
 392     if (!rbtz1
->useDaylightTime()) { 
 393         errln("FAIL: useDaylightTime returned FALSE"); 
 396     // Try to add 3rd final rule 
 397     dtr 
= new DateTimeRule(UCAL_OCTOBER
, 15, 1*HOUR
, DateTimeRule::WALL_TIME
); 
 398     atzr 
= new AnnualTimeZoneRule("3RD_ATZ", -1*HOUR
, 2*HOUR
, dtr
, STARTYEAR
, AnnualTimeZoneRule::MAX_YEAR
); 
 399     rbtz1
->addTransitionRule(atzr
, status
); 
 400     if (U_SUCCESS(status
)) { 
 401         errln("FAIL: 3rd final rule must be rejected"); 
 406     // Try to add an initial rule 
 407     InitialTimeZoneRule 
*ir1 
= new InitialTimeZoneRule("Test Initial", 2*HOUR
, 0); 
 408     rbtz1
->addTransitionRule(ir1
, status
); 
 409     if (U_SUCCESS(status
)) { 
 410         errln("FAIL: InitialTimeZoneRule must be rejected"); 
 424  * Test equivalency between OlsonTimeZone and custom RBTZ representing the 
 425  * equivalent rules in a certain time range 
 428 TimeZoneRuleTest::TestHistoricalRuleBasedTimeZone(void) { 
 429     UErrorCode status 
= U_ZERO_ERROR
; 
 431     // Compare to America/New_York with equivalent RBTZ 
 432     BasicTimeZone 
*ny 
= (BasicTimeZone
*)TimeZone::createTimeZone("America/New_York"); 
 435     InitialTimeZoneRule 
*ir 
= new InitialTimeZoneRule("EST", -5*HOUR
, 0); 
 436     RuleBasedTimeZone 
*rbtz 
= new RuleBasedTimeZone("EST5EDT", ir
); 
 439     AnnualTimeZoneRule 
*tzr
; 
 442     dtr 
= new DateTimeRule(UCAL_OCTOBER
, -1, UCAL_SUNDAY
, 
 443         2*HOUR
, DateTimeRule::WALL_TIME
); // Last Sunday in October, at 2AM wall time 
 444     tzr 
= new AnnualTimeZoneRule("EST", -5*HOUR 
/*rawOffset*/, 0 /*dstSavings*/, dtr
, 1967, 2006); 
 445     rbtz
->addTransitionRule(tzr
, status
); 
 446     if (U_FAILURE(status
)) { 
 447         errln("FAIL: couldn't add AnnualTimeZoneRule 1."); 
 450     dtr 
= new DateTimeRule(UCAL_NOVEMBER
, 1, UCAL_SUNDAY
, 
 451         true, 2*HOUR
, DateTimeRule::WALL_TIME
); // SUN>=1 in November, at 2AM wall time 
 452     tzr 
= new AnnualTimeZoneRule("EST", -5*HOUR
, 0, dtr
, 2007, AnnualTimeZoneRule::MAX_YEAR
); 
 453     rbtz
->addTransitionRule(tzr
, status
); 
 454     if (U_FAILURE(status
)) { 
 455         errln("FAIL: couldn't add AnnualTimeZoneRule 2."); 
 458     // Daylight saving time 
 459     dtr 
= new DateTimeRule(UCAL_APRIL
, -1, UCAL_SUNDAY
, 
 460         2*HOUR
, DateTimeRule::WALL_TIME
); // Last Sunday in April, at 2AM wall time 
 461     tzr 
= new AnnualTimeZoneRule("EDT", -5*HOUR
, 1*HOUR
, dtr
, 1967, 1973); 
 462     rbtz
->addTransitionRule(tzr
, status
); 
 463     if (U_FAILURE(status
)) { 
 464         errln("FAIL: couldn't add AnnualTimeZoneRule 3."); 
 467     dtr 
= new DateTimeRule(UCAL_JANUARY
, 6, 
 468         2*HOUR
, DateTimeRule::WALL_TIME
); // January 6, at 2AM wall time 
 469     tzr 
= new AnnualTimeZoneRule("EDT", -5*HOUR
, 1*HOUR
, dtr
, 1974, 1974); 
 470     rbtz
->addTransitionRule(tzr
, status
); 
 471     if (U_FAILURE(status
)) { 
 472         errln("FAIL: couldn't add AnnualTimeZoneRule 4."); 
 475     dtr 
= new DateTimeRule(UCAL_FEBRUARY
, 23, 
 476         2*HOUR
, DateTimeRule::WALL_TIME
); // February 23, at 2AM wall time 
 477     tzr 
= new AnnualTimeZoneRule("EDT", -5*HOUR
, 1*HOUR
, dtr
, 1975, 1975); 
 478     rbtz
->addTransitionRule(tzr
, status
); 
 479     if (U_FAILURE(status
)) { 
 480         errln("FAIL: couldn't add AnnualTimeZoneRule 5."); 
 483     dtr 
= new DateTimeRule(UCAL_APRIL
, -1, UCAL_SUNDAY
, 
 484         2*HOUR
, DateTimeRule::WALL_TIME
); // Last Sunday in April, at 2AM wall time 
 485     tzr 
= new AnnualTimeZoneRule("EDT", -5*HOUR
, 1*HOUR
, dtr
, 1976, 1986); 
 486     rbtz
->addTransitionRule(tzr
, status
); 
 487     if (U_FAILURE(status
)) { 
 488         errln("FAIL: couldn't add AnnualTimeZoneRule 6."); 
 491     dtr 
= new DateTimeRule(UCAL_APRIL
, 1, UCAL_SUNDAY
, 
 492         true, 2*HOUR
, DateTimeRule::WALL_TIME
); // SUN>=1 in April, at 2AM wall time 
 493     tzr 
= new AnnualTimeZoneRule("EDT", -5*HOUR
, 1*HOUR
, dtr
, 1987, 2006); 
 494     rbtz
->addTransitionRule(tzr
, status
); 
 495     if (U_FAILURE(status
)) { 
 496         errln("FAIL: couldn't add AnnualTimeZoneRule 7."); 
 499     dtr 
= new DateTimeRule(UCAL_MARCH
, 8, UCAL_SUNDAY
, 
 500         true, 2*HOUR
, DateTimeRule::WALL_TIME
); // SUN>=8 in March, at 2AM wall time 
 501     tzr 
= new AnnualTimeZoneRule("EDT", -5*HOUR
, 1*HOUR
, dtr
, 2007, AnnualTimeZoneRule::MAX_YEAR
); 
 502     rbtz
->addTransitionRule(tzr
, status
); 
 503     if (U_FAILURE(status
)) { 
 504         errln("FAIL: couldn't add AnnualTimeZoneRule 7."); 
 507     rbtz
->complete(status
); 
 508     if (U_FAILURE(status
)) { 
 509         errln("FAIL: couldn't complete RBTZ."); 
 512     // hasEquivalentTransitions 
 513     UDate jan1_1950 
= getUTCMillis(1950, UCAL_JANUARY
, 1); 
 514     UDate jan1_1967 
= getUTCMillis(1971, UCAL_JANUARY
, 1); 
 515     UDate jan1_2010 
= getUTCMillis(2010, UCAL_JANUARY
, 1);         
 517     if (!ny
->hasEquivalentTransitions(*rbtz
, jan1_1967
, jan1_2010
, TRUE
, status
)) { 
 518         dataerrln("FAIL: The RBTZ must be equivalent to America/New_York between 1967 and 2010"); 
 520     if (U_FAILURE(status
)) { 
 521         errln("FAIL: error returned from hasEquivalentTransitions for ny/rbtz 1967-2010"); 
 523     if (ny
->hasEquivalentTransitions(*rbtz
, jan1_1950
, jan1_2010
, TRUE
, status
)) { 
 524         errln("FAIL: The RBTZ must not be equivalent to America/New_York between 1950 and 2010"); 
 526     if (U_FAILURE(status
)) { 
 527         errln("FAIL: error returned from hasEquivalentTransitions for ny/rbtz 1950-2010"); 
 530     // Same with above, but calling RBTZ#hasEquivalentTransitions against OlsonTimeZone 
 531     if (!rbtz
->hasEquivalentTransitions(*ny
, jan1_1967
, jan1_2010
, TRUE
, status
)) { 
 532         dataerrln("FAIL: The RBTZ must be equivalent to America/New_York between 1967 and 2010 "); 
 534     if (U_FAILURE(status
)) { 
 535         errln("FAIL: error returned from hasEquivalentTransitions for rbtz/ny 1967-2010"); 
 537     if (rbtz
->hasEquivalentTransitions(*ny
, jan1_1950
, jan1_2010
, TRUE
, status
)) { 
 538         errln("FAIL: The RBTZ must not be equivalent to America/New_York between 1950 and 2010"); 
 540     if (U_FAILURE(status
)) { 
 541         errln("FAIL: error returned from hasEquivalentTransitions for rbtz/ny 1950-2010"); 
 545     if (ny
->hasSameRules(*rbtz
) || rbtz
->hasSameRules(*ny
)) { 
 546         errln("FAIL: hasSameRules must return false"); 
 548     RuleBasedTimeZone 
*rbtzc 
= (RuleBasedTimeZone
*)rbtz
->clone(); 
 549     if (!rbtz
->hasSameRules(*rbtzc
) || !rbtz
->hasEquivalentTransitions(*rbtzc
, jan1_1950
, jan1_2010
, TRUE
, status
)) { 
 550         errln("FAIL: hasSameRules/hasEquivalentTransitions must return true for cloned RBTZs"); 
 552     if (U_FAILURE(status
)) { 
 553         errln("FAIL: error returned from hasEquivalentTransitions for rbtz/rbtzc 1950-2010"); 
 557         getUTCMillis(2006, UCAL_MARCH
, 15), 
 558         getUTCMillis(2006, UCAL_NOVEMBER
, 1), 
 559         getUTCMillis(2007, UCAL_MARCH
, 15), 
 560         getUTCMillis(2007, UCAL_NOVEMBER
, 1), 
 561         getUTCMillis(2008, UCAL_MARCH
, 15), 
 562         getUTCMillis(2008, UCAL_NOVEMBER
, 1), 
 565     int32_t offset1
, dst1
; 
 566     int32_t offset2
, dst2
; 
 568     for (int i 
= 0; times
[i
] != 0; i
++) { 
 569         // Check getOffset - must return the same results for these time data 
 570         rbtz
->getOffset(times
[i
], FALSE
, offset1
, dst1
, status
); 
 571         if (U_FAILURE(status
)) { 
 572             errln("FAIL: rbtz->getOffset failed"); 
 574         ny
->getOffset(times
[i
], FALSE
, offset2
, dst2
, status
); 
 575         if (U_FAILURE(status
)) { 
 576             errln("FAIL: ny->getOffset failed"); 
 578         if (offset1 
!= offset2 
|| dst1 
!= dst2
) { 
 579             dataerrln("FAIL: Incompatible time zone offset/dstSavings for ny and rbtz"); 
 582         // Check inDaylightTime 
 583         if (rbtz
->inDaylightTime(times
[i
], status
) != ny
->inDaylightTime(times
[i
], status
)) { 
 584             dataerrln("FAIL: Incompatible daylight saving time for ny and rbtz"); 
 586         if (U_FAILURE(status
)) { 
 587             errln("FAIL: inDaylightTime failed"); 
 597  * Check if transitions returned by getNextTransition/getPreviousTransition 
 598  * are actual time transitions. 
 601 TimeZoneRuleTest::TestOlsonTransition(void) { 
 603     const int32_t TESTYEARS
[][2] = { 
 604         {1895, 1905}, // including int32 minimum second 
 605         {1965, 1975}, // including the epoch 
 606         {1995, 2015}, // practical year range 
 610     UErrorCode status 
= U_ZERO_ERROR
; 
 611     TestZIDEnumeration 
tzenum(!quick
); 
 613         const UnicodeString 
*tzid 
= tzenum
.snext(status
); 
 617         if (U_FAILURE(status
)) { 
 618             errln("FAIL: error returned while enumerating timezone IDs."); 
 621         BasicTimeZone 
*tz 
= (BasicTimeZone
*)TimeZone::createTimeZone(*tzid
); 
 622         for (int32_t i 
= 0; TESTYEARS
[i
][0] != 0 || TESTYEARS
[i
][1] != 0; i
++) { 
 623             UDate lo 
= getUTCMillis(TESTYEARS
[i
][0], UCAL_JANUARY
, 1); 
 624             UDate hi 
= getUTCMillis(TESTYEARS
[i
][1], UCAL_JANUARY
, 1); 
 625             verifyTransitions(*tz
, lo
, hi
); 
 632  * Check if an OlsonTimeZone and its equivalent RBTZ have the exact same 
 636 TimeZoneRuleTest::TestRBTZTransition(void) { 
 637     const int32_t STARTYEARS
[] = { 
 645     UErrorCode status 
= U_ZERO_ERROR
; 
 646     TestZIDEnumeration 
tzenum(!quick
); 
 648         const UnicodeString 
*tzid 
= tzenum
.snext(status
); 
 652         if (U_FAILURE(status
)) { 
 653             errln("FAIL: error returned while enumerating timezone IDs."); 
 656         BasicTimeZone 
*tz 
= (BasicTimeZone
*)TimeZone::createTimeZone(*tzid
); 
 657         int32_t ruleCount 
= tz
->countTransitionRules(status
); 
 659         const InitialTimeZoneRule 
*initial
; 
 660         const TimeZoneRule 
**trsrules 
= new const TimeZoneRule
*[ruleCount
]; 
 661         tz
->getTimeZoneRules(initial
, trsrules
, ruleCount
, status
); 
 662         if (U_FAILURE(status
)) { 
 663             errln((UnicodeString
)"FAIL: failed to get the TimeZoneRules from time zone " + *tzid
); 
 665         RuleBasedTimeZone 
*rbtz 
= new RuleBasedTimeZone(*tzid
, initial
->clone()); 
 666         if (U_FAILURE(status
)) { 
 667             errln((UnicodeString
)"FAIL: failed to get the transition rule count from time zone " + *tzid
); 
 669         for (int32_t i 
= 0; i 
< ruleCount
; i
++) { 
 670             rbtz
->addTransitionRule(trsrules
[i
]->clone(), status
); 
 671             if (U_FAILURE(status
)) { 
 672                 errln((UnicodeString
)"FAIL: failed to add a transition rule at index " + i 
+ " to the RBTZ for " + *tzid
); 
 675         rbtz
->complete(status
); 
 676         if (U_FAILURE(status
)) { 
 677             errln((UnicodeString
)"FAIL: complete() failed for the RBTZ for " + *tzid
); 
 680         for (int32_t idx 
= 0; STARTYEARS
[idx
] != 0; idx
++) { 
 681             UDate start 
= getUTCMillis(STARTYEARS
[idx
], UCAL_JANUARY
, 1); 
 682             UDate until 
= getUTCMillis(STARTYEARS
[idx
] + 20, UCAL_JANUARY
, 1); 
 683             // Compare the original OlsonTimeZone with the RBTZ starting the startTime for 20 years 
 686             compareTransitionsAscending(*tz
, *rbtz
, start
, until
, FALSE
); 
 687             // Ascending/inclusive 
 688             compareTransitionsAscending(*tz
, *rbtz
, start 
+ 1, until
, TRUE
); 
 690             compareTransitionsDescending(*tz
, *rbtz
, start
, until
, FALSE
); 
 691             // Descending/inclusive 
 692             compareTransitionsDescending(*tz
, *rbtz
, start 
+ 1, until
, TRUE
); 
 701 TimeZoneRuleTest::TestHasEquivalentTransitions(void) { 
 702     // America/New_York and America/Indiana/Indianapolis are equivalent 
 704     UErrorCode status 
= U_ZERO_ERROR
; 
 705     BasicTimeZone 
*newyork 
= (BasicTimeZone
*)TimeZone::createTimeZone("America/New_York"); 
 706     BasicTimeZone 
*indianapolis 
= (BasicTimeZone
*)TimeZone::createTimeZone("America/Indiana/Indianapolis"); 
 707     BasicTimeZone 
*gmt_5 
= (BasicTimeZone
*)TimeZone::createTimeZone("Etc/GMT+5"); 
 709     UDate jan1_1971 
= getUTCMillis(1971, UCAL_JANUARY
, 1); 
 710     UDate jan1_2005 
= getUTCMillis(2005, UCAL_JANUARY
, 1); 
 711     UDate jan1_2006 
= getUTCMillis(2006, UCAL_JANUARY
, 1); 
 712     UDate jan1_2007 
= getUTCMillis(2007, UCAL_JANUARY
, 1); 
 713     UDate jan1_2011 
= getUTCMillis(2010, UCAL_JANUARY
, 1); 
 715     if (newyork
->hasEquivalentTransitions(*indianapolis
, jan1_2005
, jan1_2011
, TRUE
, status
)) { 
 716         dataerrln("FAIL: New_York is not equivalent to Indianapolis between 2005 and 2010"); 
 718     if (U_FAILURE(status
)) { 
 719         errln("FAIL: error status is returned from hasEquivalentTransition"); 
 721     if (!newyork
->hasEquivalentTransitions(*indianapolis
, jan1_2006
, jan1_2011
, TRUE
, status
)) { 
 722         errln("FAIL: New_York is equivalent to Indianapolis between 2006 and 2010"); 
 724     if (U_FAILURE(status
)) { 
 725         errln("FAIL: error status is returned from hasEquivalentTransition"); 
 728     if (!indianapolis
->hasEquivalentTransitions(*gmt_5
, jan1_1971
, jan1_2006
, TRUE
, status
)) { 
 729         errln("FAIL: Indianapolis is equivalent to GMT+5 between 1971 and 2005"); 
 731     if (U_FAILURE(status
)) { 
 732         errln("FAIL: error status is returned from hasEquivalentTransition"); 
 734     if (indianapolis
->hasEquivalentTransitions(*gmt_5
, jan1_1971
, jan1_2007
, TRUE
, status
)) { 
 735         dataerrln("FAIL: Indianapolis is not equivalent to GMT+5 between 1971 and 2006"); 
 737     if (U_FAILURE(status
)) { 
 738         errln("FAIL: error status is returned from hasEquivalentTransition"); 
 742     BasicTimeZone 
*newyork2 
= (BasicTimeZone
*)newyork
->clone(); 
 743     if (!newyork
->hasEquivalentTransitions(*newyork2
, jan1_1971
, jan1_2011
, FALSE
, status
)) { 
 744         errln("FAIL: Cloned TimeZone must have the same transitions"); 
 746     if (U_FAILURE(status
)) { 
 747         errln("FAIL: error status is returned from hasEquivalentTransition for newyork/newyork2"); 
 749     if (!newyork
->hasEquivalentTransitions(*newyork2
, jan1_1971
, jan1_2011
, TRUE
, status
)) { 
 750         errln("FAIL: Cloned TimeZone must have the same transitions"); 
 752     if (U_FAILURE(status
)) { 
 753         errln("FAIL: error status is returned from hasEquivalentTransition for newyork/newyork2"); 
 756     // America/New_York and America/Los_Angeles has same DST start rules, but 
 757     // raw offsets are different 
 758     BasicTimeZone 
*losangeles 
= (BasicTimeZone
*)TimeZone::createTimeZone("America/Los_Angeles"); 
 759     if (newyork
->hasEquivalentTransitions(*losangeles
, jan1_2006
, jan1_2011
, TRUE
, status
)) { 
 760         dataerrln("FAIL: New_York is not equivalent to Los Angeles, but returned true"); 
 762     if (U_FAILURE(status
)) { 
 763         errln("FAIL: error status is returned from hasEquivalentTransition for newyork/losangeles"); 
 774  * Write out time zone rules of OlsonTimeZone into VTIMEZONE format, create a new 
 775  * VTimeZone from the VTIMEZONE data, then compare transitions 
 778 TimeZoneRuleTest::TestVTimeZoneRoundTrip(void) { 
 779     UDate startTime 
= getUTCMillis(1850, UCAL_JANUARY
, 1); 
 780     UDate endTime 
= getUTCMillis(2050, UCAL_JANUARY
, 1); 
 782     UErrorCode status 
= U_ZERO_ERROR
; 
 783     TestZIDEnumeration 
tzenum(!quick
); 
 785         const UnicodeString 
*tzid 
= tzenum
.snext(status
); 
 789         if (U_FAILURE(status
)) { 
 790             errln("FAIL: error returned while enumerating timezone IDs."); 
 793         BasicTimeZone 
*tz 
= (BasicTimeZone
*)TimeZone::createTimeZone(*tzid
); 
 794         VTimeZone 
*vtz_org 
= VTimeZone::createVTimeZoneByID(*tzid
); 
 795         vtz_org
->setTZURL("http://source.icu-project.org/timezone"); 
 796         vtz_org
->setLastModified(Calendar::getNow()); 
 797         VTimeZone 
*vtz_new 
= NULL
; 
 798         UnicodeString vtzdata
; 
 799         // Write out VTIMEZONE data 
 800         vtz_org
->write(vtzdata
, status
); 
 801         if (U_FAILURE(status
)) { 
 802             errln((UnicodeString
)"FAIL: error returned while writing time zone rules for " + 
 803                 *tzid 
+ " into VTIMEZONE format."); 
 805             // Read VTIMEZONE data 
 806             vtz_new 
= VTimeZone::createVTimeZone(vtzdata
, status
); 
 807             if (U_FAILURE(status
)) { 
 808                 errln((UnicodeString
)"FAIL: error returned while reading VTIMEZONE data for " + *tzid
); 
 810                 // Write out VTIMEZONE one more time 
 811                 UnicodeString vtzdata1
; 
 812                 vtz_new
->write(vtzdata1
, status
); 
 813                 if (U_FAILURE(status
)) { 
 814                     errln((UnicodeString
)"FAIL: error returned while writing time zone rules for " + 
 815                         *tzid 
+ "(vtz_new) into VTIMEZONE format."); 
 817                     // Make sure VTIMEZONE data is exactly same with the first one 
 818                     if (vtzdata 
!= vtzdata1
) { 
 819                         errln((UnicodeString
)"FAIL: different VTIMEZONE data after round trip for " + *tzid
); 
 822                 // Check equivalency after the first transition. 
 823                 // The DST information before the first transition might be lost 
 824                 // because there is no good way to represent the initial time with 
 826                 int32_t raw1
, raw2
, dst1
, dst2
; 
 827                 tz
->getOffset(startTime
, FALSE
, raw1
, dst1
, status
); 
 828                 vtz_new
->getOffset(startTime
, FALSE
, raw2
, dst2
, status
); 
 829                 if (U_FAILURE(status
)) { 
 830                     errln("FAIL: error status is returned from getOffset"); 
 832                     if (raw1 
+ dst1 
!= raw2 
+ dst2
) { 
 833                         errln("FAIL: VTimeZone for " + *tzid 
+ 
 834                             " is not equivalent to its OlsonTimeZone corresponding at " 
 835                             + dateToString(startTime
)); 
 837                     TimeZoneTransition trans
; 
 838                     UBool avail 
= tz
->getNextTransition(startTime
, FALSE
, trans
); 
 840                         if (!vtz_new
->hasEquivalentTransitions(*tz
, trans
.getTime(), 
 841                                 endTime
, TRUE
, status
)) { 
 842                             int32_t maxDelta 
= 1000; 
 843                             if (!hasEquivalentTransitions(*vtz_new
, *tz
, trans
.getTime() + maxDelta
, 
 844                                 endTime
, TRUE
, maxDelta
, status
)) { 
 845                                 errln("FAIL: VTimeZone for " + *tzid 
+ 
 846                                     " is not equivalent to its OlsonTimeZone corresponding."); 
 848                                 logln("VTimeZone for " + *tzid 
+ 
 849                                     "  differs from its OlsonTimeZone corresponding with maximum transition time delta - " + maxDelta
); 
 852                         if (U_FAILURE(status
)) { 
 853                             errln("FAIL: error status is returned from hasEquivalentTransition"); 
 858             if (vtz_new 
!= NULL
) { 
 869  * Write out time zone rules of OlsonTimeZone after a cutover date into VTIMEZONE format, 
 870  * create a new VTimeZone from the VTIMEZONE data, then compare transitions 
 873 TimeZoneRuleTest::TestVTimeZoneRoundTripPartial(void) { 
 874     const int32_t STARTYEARS
[] = { 
 880     UDate endTime 
= getUTCMillis(2050, UCAL_JANUARY
, 1); 
 882     UErrorCode status 
= U_ZERO_ERROR
; 
 883     TestZIDEnumeration 
tzenum(!quick
); 
 885         const UnicodeString 
*tzid 
= tzenum
.snext(status
); 
 889         if (U_FAILURE(status
)) { 
 890             errln("FAIL: error returned while enumerating timezone IDs."); 
 893         BasicTimeZone 
*tz 
= (BasicTimeZone
*)TimeZone::createTimeZone(*tzid
); 
 894         VTimeZone 
*vtz_org 
= VTimeZone::createVTimeZoneByID(*tzid
); 
 895         VTimeZone 
*vtz_new 
= NULL
; 
 896         UnicodeString vtzdata
; 
 898         for (int32_t i 
= 0; STARTYEARS
[i
] != 0; i
++) { 
 899             // Write out VTIMEZONE 
 900             UDate startTime 
= getUTCMillis(STARTYEARS
[i
], UCAL_JANUARY
, 1); 
 901             vtz_org
->write(startTime
, vtzdata
, status
); 
 902             if (U_FAILURE(status
)) { 
 903                 errln((UnicodeString
)"FAIL: error returned while writing time zone rules for " + 
 904                     *tzid 
+ " into VTIMEZONE format since " + dateToString(startTime
)); 
 906                 // Read VTIMEZONE data 
 907                 vtz_new 
= VTimeZone::createVTimeZone(vtzdata
, status
); 
 908                 if (U_FAILURE(status
)) { 
 909                     errln((UnicodeString
)"FAIL: error returned while reading VTIMEZONE data for " + *tzid
 
 910                         + " since " + dateToString(startTime
)); 
 912                     // Check equivalency after the first transition. 
 913                     // The DST information before the first transition might be lost 
 914                     // because there is no good way to represent the initial time with 
 916                     int32_t raw1
, raw2
, dst1
, dst2
; 
 917                     tz
->getOffset(startTime
, FALSE
, raw1
, dst1
, status
); 
 918                     vtz_new
->getOffset(startTime
, FALSE
, raw2
, dst2
, status
); 
 919                     if (U_FAILURE(status
)) { 
 920                         errln("FAIL: error status is returned from getOffset"); 
 922                         if (raw1 
+ dst1 
!= raw2 
+ dst2
) { 
 923                             errln("FAIL: VTimeZone for " + *tzid 
+ 
 924                                 " is not equivalent to its OlsonTimeZone corresponding at " 
 925                                 + dateToString(startTime
)); 
 927                         TimeZoneTransition trans
; 
 928                         UBool avail 
= tz
->getNextTransition(startTime
, FALSE
, trans
); 
 930                             if (!vtz_new
->hasEquivalentTransitions(*tz
, trans
.getTime(), 
 931                                     endTime
, TRUE
, status
)) { 
 932                                 int32_t maxDelta 
= 1000; 
 933                                 if (!hasEquivalentTransitions(*vtz_new
, *tz
, trans
.getTime() + maxDelta
, 
 934                                     endTime
, TRUE
, maxDelta
, status
)) { 
 935                                     errln("FAIL: VTimeZone for " + *tzid 
+ 
 936                                         " is not equivalent to its OlsonTimeZone corresponding."); 
 938                                     logln("VTimeZone for " + *tzid 
+ 
 939                                         "  differs from its OlsonTimeZone corresponding with maximum transition time delta - " + maxDelta
); 
 943                             if (U_FAILURE(status
)) { 
 944                                 errln("FAIL: error status is returned from hasEquivalentTransition"); 
 950             if (vtz_new 
!= NULL
) { 
 961  * Write out simple time zone rules from an OlsonTimeZone at various time into VTIMEZONE 
 962  * format and create a new VTimeZone from the VTIMEZONE data, then make sure the raw offset 
 963  * and DST savings are same in these two time zones. 
 966 TimeZoneRuleTest::TestVTimeZoneSimpleWrite(void) { 
 967     const int32_t TESTDATES
[][3] = { 
 968         {2006,  UCAL_JANUARY
,   1}, 
 969         {2006,  UCAL_MARCH
,     15}, 
 970         {2006,  UCAL_MARCH
,     31}, 
 971         {2006,  UCAL_OCTOBER
,   25}, 
 972         {2006,  UCAL_NOVEMBER
,  1}, 
 973         {2006,  UCAL_NOVEMBER
,  5}, 
 974         {2007,  UCAL_JANUARY
,   1}, 
 978     UErrorCode status 
= U_ZERO_ERROR
; 
 979     TestZIDEnumeration 
tzenum(!quick
); 
 981         const UnicodeString 
*tzid 
= tzenum
.snext(status
); 
 985         if (U_FAILURE(status
)) { 
 986             errln("FAIL: error returned while enumerating timezone IDs."); 
 989         VTimeZone 
*vtz_org 
= VTimeZone::createVTimeZoneByID(*tzid
); 
 990         VTimeZone 
*vtz_new 
= NULL
; 
 991         UnicodeString vtzdata
; 
 993         for (int32_t i 
= 0; TESTDATES
[i
][0] != 0; i
++) { 
 994             // Write out VTIMEZONE 
 995             UDate time 
= getUTCMillis(TESTDATES
[i
][0], TESTDATES
[i
][1], TESTDATES
[i
][2]); 
 996             vtz_org
->writeSimple(time
, vtzdata
, status
); 
 997             if (U_FAILURE(status
)) { 
 998                 errln((UnicodeString
)"FAIL: error returned while writing simple time zone rules for " + 
 999                     *tzid 
+ " into VTIMEZONE format at " + dateToString(time
)); 
1001                 // Read VTIMEZONE data 
1002                 vtz_new 
= VTimeZone::createVTimeZone(vtzdata
, status
); 
1003                 if (U_FAILURE(status
)) { 
1004                     errln((UnicodeString
)"FAIL: error returned while reading simple VTIMEZONE data for " + *tzid
 
1005                         + " at " + dateToString(time
)); 
1007                     // Check equivalency 
1010                     vtz_org
->getOffset(time
, FALSE
, raw0
, dst0
, status
); 
1011                     vtz_new
->getOffset(time
, FALSE
, raw1
, dst1
, status
); 
1012                     if (U_SUCCESS(status
)) { 
1013                         if (raw0 
!= raw1 
|| dst0 
!= dst1
) { 
1014                             errln("FAIL: VTimeZone writeSimple for " + *tzid 
+ " at " 
1015                                 + dateToString(time
) + " failed to the round trip."); 
1018                         errln("FAIL: getOffset returns error status"); 
1022             if (vtz_new 
!= NULL
) { 
1032  * Write out time zone rules of OlsonTimeZone into VTIMEZONE format with RFC2445 header TZURL and 
1033  * LAST-MODIFIED, create a new VTimeZone from the VTIMEZONE data to see if the headers are preserved. 
1036 TimeZoneRuleTest::TestVTimeZoneHeaderProps(void) { 
1037     const UnicodeString 
TESTURL1("http://source.icu-project.org"); 
1038     const UnicodeString 
TESTURL2("http://www.ibm.com"); 
1040     UErrorCode status 
= U_ZERO_ERROR
; 
1041     UnicodeString tzurl
; 
1043     UDate lastmod 
= getUTCMillis(2007, UCAL_JUNE
, 1); 
1044     VTimeZone 
*vtz 
= VTimeZone::createVTimeZoneByID("America/Chicago"); 
1045     vtz
->setTZURL(TESTURL1
); 
1046     vtz
->setLastModified(lastmod
); 
1048     // Roundtrip conversion 
1049     UnicodeString vtzdata
; 
1050     vtz
->write(vtzdata
, status
); 
1051     VTimeZone 
*newvtz1 
= NULL
; 
1052     if (U_FAILURE(status
)) { 
1053         errln("FAIL: error returned while writing VTIMEZONE data 1"); 
1057     newvtz1 
= VTimeZone::createVTimeZone(vtzdata
, status
); 
1058     if (U_FAILURE(status
)) { 
1059         errln("FAIL: error returned while loading VTIMEZONE data 1"); 
1061         // Check if TZURL and LAST-MODIFIED properties are preserved 
1062         newvtz1
->getTZURL(tzurl
); 
1063         if (tzurl 
!= TESTURL1
) { 
1064             errln("FAIL: TZURL 1 was not preserved"); 
1066         vtz
->getLastModified(lmod
); 
1067         if (lastmod 
!= lmod
) { 
1068             errln("FAIL: LAST-MODIFIED was not preserved"); 
1072     if (U_SUCCESS(status
)) { 
1073         // Set different tzurl 
1074         newvtz1
->setTZURL(TESTURL2
); 
1076         // Second roundtrip, with a cutover 
1077         newvtz1
->write(vtzdata
, status
); 
1078         if (U_FAILURE(status
)) { 
1079             errln("FAIL: error returned while writing VTIMEZONE data 2"); 
1081             VTimeZone 
*newvtz2 
= VTimeZone::createVTimeZone(vtzdata
, status
); 
1082             if (U_FAILURE(status
)) { 
1083                 errln("FAIL: error returned while loading VTIMEZONE data 2"); 
1085                 // Check if TZURL and LAST-MODIFIED properties are preserved 
1086                 newvtz2
->getTZURL(tzurl
); 
1087                 if (tzurl 
!= TESTURL2
) { 
1088                     errln("FAIL: TZURL was not preserved in the second roundtrip"); 
1090                 vtz
->getLastModified(lmod
); 
1091                 if (lastmod 
!= lmod
) { 
1092                     errln("FAIL: LAST-MODIFIED was not preserved in the second roundtrip"); 
1103  * Extract simple rules from an OlsonTimeZone and make sure the rule format matches 
1104  * the expected format. 
1107 TimeZoneRuleTest::TestGetSimpleRules(void) { 
1108     UDate testTimes
[] = { 
1109         getUTCMillis(1970, UCAL_JANUARY
, 1), 
1110         getUTCMillis(2000, UCAL_MARCH
, 31), 
1111         getUTCMillis(2005, UCAL_JULY
, 1), 
1112         getUTCMillis(2010, UCAL_NOVEMBER
, 1),         
1114     int32_t numTimes 
= UPRV_LENGTHOF(testTimes
); 
1115     UErrorCode status 
= U_ZERO_ERROR
; 
1116     TestZIDEnumeration 
tzenum(!quick
); 
1117     InitialTimeZoneRule 
*initial
; 
1118     AnnualTimeZoneRule 
*std
, *dst
; 
1119     for (int32_t i 
= 0; i 
< numTimes 
; i
++) { 
1121             const UnicodeString 
*tzid 
= tzenum
.snext(status
); 
1125             if (U_FAILURE(status
)) { 
1126                 errln("FAIL: error returned while enumerating timezone IDs."); 
1129             BasicTimeZone 
*tz 
= (BasicTimeZone
*)TimeZone::createTimeZone(*tzid
); 
1132             tz
->getSimpleRulesNear(testTimes
[i
], initial
, std
, dst
, status
); 
1133             if (U_FAILURE(status
)) { 
1134                 errln("FAIL: getSimpleRules failed."); 
1137             if (initial 
== NULL
) { 
1138                 errln("FAIL: initial rule must not be NULL"); 
1140             } else if (!((std 
== NULL 
&& dst 
== NULL
) || (std 
!= NULL 
&& dst 
!= NULL
))) { 
1141                 errln("FAIL: invalid std/dst pair."); 
1145                 const DateTimeRule 
*dtr 
= std
->getRule(); 
1146                 if (dtr
->getDateRuleType() != DateTimeRule::DOW
) { 
1147                     errln("FAIL: simple std rull must use DateTimeRule::DOW as date rule."); 
1150                 if (dtr
->getTimeRuleType() != DateTimeRule::WALL_TIME
) { 
1151                     errln("FAIL: simple std rull must use DateTimeRule::WALL_TIME as time rule."); 
1154                 dtr 
= dst
->getRule(); 
1155                 if (dtr
->getDateRuleType() != DateTimeRule::DOW
) { 
1156                     errln("FAIL: simple dst rull must use DateTimeRule::DOW as date rule."); 
1159                 if (dtr
->getTimeRuleType() != DateTimeRule::WALL_TIME
) { 
1160                     errln("FAIL: simple dst rull must use DateTimeRule::WALL_TIME as time rule."); 
1164             // Create an RBTZ from the rules and compare the offsets at the date 
1165             RuleBasedTimeZone 
*rbtz 
= new RuleBasedTimeZone(*tzid
, initial
); 
1167                 rbtz
->addTransitionRule(std
, status
); 
1168                 if (U_FAILURE(status
)) { 
1169                     errln("FAIL: couldn't add std rule."); 
1171                 rbtz
->addTransitionRule(dst
, status
); 
1172                 if (U_FAILURE(status
)) { 
1173                     errln("FAIL: couldn't add dst rule."); 
1176             rbtz
->complete(status
); 
1177             if (U_FAILURE(status
)) { 
1178                 errln("FAIL: couldn't complete rbtz for " + *tzid
); 
1181             int32_t raw0
, dst0
, raw1
, dst1
; 
1182             tz
->getOffset(testTimes
[i
], FALSE
, raw0
, dst0
, status
); 
1183             if (U_FAILURE(status
)) { 
1184                 errln("FAIL: couldn't get offsets from tz for " + *tzid
); 
1186             rbtz
->getOffset(testTimes
[i
], FALSE
, raw1
, dst1
, status
); 
1187             if (U_FAILURE(status
)) { 
1188                 errln("FAIL: couldn't get offsets from rbtz for " + *tzid
); 
1190             if (raw0 
!= raw1 
|| dst0 
!= dst1
) { 
1191                 errln("FAIL: rbtz created by simple rule does not match the original tz for tzid " + *tzid
); 
1200  * API coverage tests for TimeZoneRule  
1203 TimeZoneRuleTest::TestTimeZoneRuleCoverage(void) { 
1204     UDate time1 
= getUTCMillis(2005, UCAL_JULY
, 4); 
1205     UDate time2 
= getUTCMillis(2015, UCAL_JULY
, 4); 
1206     UDate time3 
= getUTCMillis(1950, UCAL_JULY
, 4); 
1208     DateTimeRule 
*dtr1 
= new DateTimeRule(UCAL_FEBRUARY
, 29, UCAL_SUNDAY
, FALSE
, 
1209             3*HOUR
, DateTimeRule::WALL_TIME
); // Last Sunday on or before Feb 29, at 3 AM, wall time 
1210     DateTimeRule 
*dtr2 
= new DateTimeRule(UCAL_MARCH
, 11, 2*HOUR
, 
1211             DateTimeRule::STANDARD_TIME
); // Mar 11, at 2 AM, standard time 
1212     DateTimeRule 
*dtr3 
= new DateTimeRule(UCAL_OCTOBER
, -1, UCAL_SATURDAY
, 
1213             6*HOUR
, DateTimeRule::UTC_TIME
); //Last Saturday in Oct, at 6 AM, UTC 
1214     DateTimeRule 
*dtr4 
= new DateTimeRule(UCAL_MARCH
, 8, UCAL_SUNDAY
, TRUE
, 
1215             2*HOUR
, DateTimeRule::WALL_TIME
); // First Sunday on or after Mar 8, at 2 AM, wall time 
1217     AnnualTimeZoneRule 
*a1 
= new AnnualTimeZoneRule("a1", -3*HOUR
, 1*HOUR
, *dtr1
, 
1218             2000, AnnualTimeZoneRule::MAX_YEAR
); 
1219     AnnualTimeZoneRule 
*a2 
= new AnnualTimeZoneRule("a2", -3*HOUR
, 1*HOUR
, *dtr1
, 
1220             2000, AnnualTimeZoneRule::MAX_YEAR
); 
1221     AnnualTimeZoneRule 
*a3 
= new AnnualTimeZoneRule("a3", -3*HOUR
, 1*HOUR
, *dtr1
, 
1224     InitialTimeZoneRule 
*i1 
= new InitialTimeZoneRule("i1", -3*HOUR
, 0); 
1225     InitialTimeZoneRule 
*i2 
= new InitialTimeZoneRule("i2", -3*HOUR
, 0); 
1226     InitialTimeZoneRule 
*i3 
= new InitialTimeZoneRule("i3", -3*HOUR
, 1*HOUR
); 
1228     UDate trtimes1
[] = {0.0}; 
1229     UDate trtimes2
[] = {0.0, 10000000.0}; 
1231     TimeArrayTimeZoneRule 
*t1 
= new TimeArrayTimeZoneRule("t1", -3*HOUR
, 0, trtimes1
, 1, DateTimeRule::UTC_TIME
); 
1232     TimeArrayTimeZoneRule 
*t2 
= new TimeArrayTimeZoneRule("t2", -3*HOUR
, 0, trtimes1
, 1, DateTimeRule::UTC_TIME
); 
1233     TimeArrayTimeZoneRule 
*t3 
= new TimeArrayTimeZoneRule("t3", -3*HOUR
, 0, trtimes2
, 2, DateTimeRule::UTC_TIME
); 
1234     TimeArrayTimeZoneRule 
*t4 
= new TimeArrayTimeZoneRule("t4", -3*HOUR
, 0, trtimes1
, 1, DateTimeRule::STANDARD_TIME
); 
1235     TimeArrayTimeZoneRule 
*t5 
= new TimeArrayTimeZoneRule("t5", -4*HOUR
, 1*HOUR
, trtimes1
, 1, DateTimeRule::WALL_TIME
); 
1237     // DateTimeRule::operator=/clone 
1238     DateTimeRule 
dtr0(UCAL_MAY
, 31, 2*HOUR
, DateTimeRule::WALL_TIME
); 
1239     if (dtr0 
== *dtr1 
|| !(dtr0 
!= *dtr1
)) { 
1240         errln("FAIL: DateTimeRule dtr0 is not equal to dtr1, but got wrong result"); 
1243     if (dtr0 
!= *dtr1 
|| !(dtr0 
== *dtr1
)) { 
1244         errln("FAIL: DateTimeRule dtr0 is equal to dtr1, but got wrong result"); 
1246     DateTimeRule 
*dtr0c 
= dtr0
.clone(); 
1247     if (*dtr0c 
!= *dtr1 
|| !(*dtr0c 
== *dtr1
)) { 
1248         errln("FAIL: DateTimeRule dtr0c is equal to dtr1, but got wrong result"); 
1252     // AnnualTimeZonerule::operator=/clone 
1253     AnnualTimeZoneRule 
a0("a0", 5*HOUR
, 1*HOUR
, *dtr1
, 1990, AnnualTimeZoneRule::MAX_YEAR
); 
1254     if (a0 
== *a1 
|| !(a0 
!= *a1
)) { 
1255         errln("FAIL: AnnualTimeZoneRule a0 is not equal to a1, but got wrong result"); 
1258     if (a0 
!= *a1 
|| !(a0 
== *a1
)) { 
1259         errln("FAIL: AnnualTimeZoneRule a0 is equal to a1, but got wrong result"); 
1261     AnnualTimeZoneRule 
*a0c 
= a0
.clone(); 
1262     if (*a0c 
!= *a1 
|| !(*a0c 
== *a1
)) { 
1263         errln("FAIL: AnnualTimeZoneRule a0c is equal to a1, but got wrong result"); 
1267     // AnnualTimeZoneRule::getRule 
1268     if (*(a1
->getRule()) != *(a2
->getRule())) { 
1269         errln("FAIL: The same DateTimeRule must be returned from AnnualTimeZoneRule a1 and a2"); 
1272     // AnnualTimeZoneRule::getStartYear 
1273     int32_t startYear 
= a1
->getStartYear(); 
1274     if (startYear 
!= 2000) { 
1275         errln((UnicodeString
)"FAIL: The start year of AnnualTimeZoneRule a1 must be 2000 - returned: " + startYear
); 
1278     // AnnualTimeZoneRule::getEndYear 
1279     int32_t endYear 
= a1
->getEndYear(); 
1280     if (endYear 
!= AnnualTimeZoneRule::MAX_YEAR
) { 
1281         errln((UnicodeString
)"FAIL: The start year of AnnualTimeZoneRule a1 must be MAX_YEAR - returned: " + endYear
); 
1283     endYear 
= a3
->getEndYear(); 
1284     if (endYear 
!= 2010) { 
1285         errln((UnicodeString
)"FAIL: The start year of AnnualTimeZoneRule a3 must be 2010 - returned: " + endYear
); 
1288     // AnnualTimeZone::getStartInYear 
1291     b1 
= a1
->getStartInYear(2005, -3*HOUR
, 0, d1
); 
1292     b2 
= a3
->getStartInYear(2005, -3*HOUR
, 0, d2
); 
1293     if (!b1 
|| !b2 
|| d1 
!= d2
) { 
1294         errln("FAIL: AnnualTimeZoneRule::getStartInYear did not work as expected"); 
1296     b2 
= a3
->getStartInYear(2015, -3*HOUR
, 0, d2
); 
1298         errln("FAIL: AnnualTimeZoneRule::getStartInYear returned TRUE for 2015 which is out of rule range"); 
1301     // AnnualTimeZone::getFirstStart 
1302     b1 
= a1
->getFirstStart(-3*HOUR
, 0, d1
); 
1303     b2 
= a1
->getFirstStart(-4*HOUR
, 1*HOUR
, d2
); 
1304     if (!b1 
|| !b2 
|| d1 
!= d2
) { 
1305         errln("FAIL: The same start time should be returned by getFirstStart"); 
1308     // AnnualTimeZone::getFinalStart 
1309     b1 
= a1
->getFinalStart(-3*HOUR
, 0, d1
); 
1311         errln("FAIL: getFinalStart returned TRUE for a1"); 
1313     b1 
= a1
->getStartInYear(2010, -3*HOUR
, 0, d1
); 
1314     b2 
= a3
->getFinalStart(-3*HOUR
, 0, d2
); 
1315     if (!b1 
|| !b2 
|| d1 
!= d2
) { 
1316         errln("FAIL: Bad date is returned by getFinalStart"); 
1319     // AnnualTimeZone::getNextStart / getPreviousStart 
1320     b1 
= a1
->getNextStart(time1
, -3*HOUR
, 0, FALSE
, d1
); 
1322         errln("FAIL: getNextStart returned FALSE for ai"); 
1324         b2 
= a1
->getPreviousStart(d1
, -3*HOUR
, 0, TRUE
, d2
); 
1325         if (!b2 
|| d1 
!= d2
) { 
1326             errln("FAIL: Bad Date is returned by getPreviousStart"); 
1329     b1 
= a3
->getNextStart(time2
, -3*HOUR
, 0, FALSE
, d1
); 
1331         dataerrln("FAIL: getNextStart must return FALSE when no start time is available after the base time"); 
1333     b1 
= a3
->getFinalStart(-3*HOUR
, 0, d1
); 
1334     b2 
= a3
->getPreviousStart(time2
, -3*HOUR
, 0, FALSE
, d2
); 
1335     if (!b1 
|| !b2 
|| d1 
!= d2
) { 
1336         dataerrln("FAIL: getPreviousStart does not match with getFinalStart after the end year"); 
1339     // AnnualTimeZone::isEquavalentTo 
1340     if (!a1
->isEquivalentTo(*a2
)) { 
1341         errln("FAIL: AnnualTimeZoneRule a1 is equivalent to a2, but returned FALSE"); 
1343     if (a1
->isEquivalentTo(*a3
)) { 
1344         errln("FAIL: AnnualTimeZoneRule a1 is not equivalent to a3, but returned TRUE"); 
1346     if (!a1
->isEquivalentTo(*a1
)) { 
1347         errln("FAIL: AnnualTimeZoneRule a1 is equivalent to itself, but returned FALSE"); 
1349     if (a1
->isEquivalentTo(*t1
)) { 
1350         errln("FAIL: AnnualTimeZoneRule is not equivalent to TimeArrayTimeZoneRule, but returned TRUE"); 
1353     // InitialTimezoneRule::operator=/clone 
1354     InitialTimeZoneRule 
i0("i0", 10*HOUR
, 0); 
1355     if (i0 
== *i1 
|| !(i0 
!= *i1
)) { 
1356         errln("FAIL: InitialTimeZoneRule i0 is not equal to i1, but got wrong result"); 
1359     if (i0 
!= *i1 
|| !(i0 
== *i1
)) { 
1360         errln("FAIL: InitialTimeZoneRule i0 is equal to i1, but got wrong result"); 
1362     InitialTimeZoneRule 
*i0c 
= i0
.clone(); 
1363     if (*i0c 
!= *i1 
|| !(*i0c 
== *i1
)) { 
1364         errln("FAIL: InitialTimeZoneRule i0c is equal to i1, but got wrong result"); 
1368     // InitialTimeZoneRule::isEquivalentRule 
1369     if (!i1
->isEquivalentTo(*i2
)) { 
1370         errln("FAIL: InitialTimeZoneRule i1 is equivalent to i2, but returned FALSE"); 
1372     if (i1
->isEquivalentTo(*i3
)) { 
1373         errln("FAIL: InitialTimeZoneRule i1 is not equivalent to i3, but returned TRUE"); 
1375     if (i1
->isEquivalentTo(*a1
)) { 
1376         errln("FAIL: An InitialTimeZoneRule is not equivalent to an AnnualTimeZoneRule, but returned TRUE"); 
1379     // InitialTimeZoneRule::getFirstStart/getFinalStart/getNextStart/getPreviousStart 
1380     b1 
= i1
->getFirstStart(0, 0, d1
); 
1382         errln("FAIL: InitialTimeZone::getFirstStart returned TRUE"); 
1384     b1 
= i1
->getFinalStart(0, 0, d1
); 
1386         errln("FAIL: InitialTimeZone::getFinalStart returned TRUE"); 
1388     b1 
= i1
->getNextStart(time1
, 0, 0, FALSE
, d1
); 
1390         errln("FAIL: InitialTimeZone::getNextStart returned TRUE"); 
1392     b1 
= i1
->getPreviousStart(time1
, 0, 0, FALSE
, d1
); 
1394         errln("FAIL: InitialTimeZone::getPreviousStart returned TRUE"); 
1397     // TimeArrayTimeZoneRule::operator=/clone 
1398     TimeArrayTimeZoneRule 
t0("t0", 4*HOUR
, 0, trtimes1
, 1, DateTimeRule::UTC_TIME
); 
1399     if (t0 
== *t1 
|| !(t0 
!= *t1
)) { 
1400         errln("FAIL: TimeArrayTimeZoneRule t0 is not equal to t1, but got wrong result"); 
1403     if (t0 
!= *t1 
|| !(t0 
== *t1
)) { 
1404         errln("FAIL: TimeArrayTimeZoneRule t0 is equal to t1, but got wrong result"); 
1406     TimeArrayTimeZoneRule 
*t0c 
= t0
.clone(); 
1407     if (*t0c 
!= *t1 
|| !(*t0c 
== *t1
)) { 
1408         errln("FAIL: TimeArrayTimeZoneRule t0c is equal to t1, but got wrong result"); 
1412     // TimeArrayTimeZoneRule::countStartTimes 
1413     if (t1
->countStartTimes() != 1) { 
1414         errln("FAIL: Bad start time count is returned by TimeArrayTimeZoneRule::countStartTimes"); 
1417     // TimeArrayTimeZoneRule::getStartTimeAt 
1418     b1 
= t1
->getStartTimeAt(-1, d1
); 
1420         errln("FAIL: TimeArrayTimeZoneRule::getStartTimeAt returned TRUE for index -1"); 
1422     b1 
= t1
->getStartTimeAt(0, d1
); 
1423     if (!b1 
|| d1 
!= trtimes1
[0]) { 
1424         errln("FAIL: TimeArrayTimeZoneRule::getStartTimeAt returned incorrect result for index 0"); 
1426     b1 
= t1
->getStartTimeAt(1, d1
); 
1428         errln("FAIL: TimeArrayTimeZoneRule::getStartTimeAt returned TRUE for index 1"); 
1431     // TimeArrayTimeZoneRule::getTimeType 
1432     if (t1
->getTimeType() != DateTimeRule::UTC_TIME
) { 
1433         errln("FAIL: TimeArrayTimeZoneRule t1 uses UTC_TIME, but different type is returned"); 
1435     if (t4
->getTimeType() != DateTimeRule::STANDARD_TIME
) { 
1436         errln("FAIL: TimeArrayTimeZoneRule t4 uses STANDARD_TIME, but different type is returned"); 
1438     if (t5
->getTimeType() != DateTimeRule::WALL_TIME
) { 
1439         errln("FAIL: TimeArrayTimeZoneRule t5 uses WALL_TIME, but different type is returned"); 
1442     // TimeArrayTimeZoneRule::getFirstStart/getFinalStart 
1443     b1 
= t1
->getFirstStart(0, 0, d1
); 
1444     if (!b1 
|| d1 
!= trtimes1
[0]) { 
1445         errln("FAIL: Bad first start time returned from TimeArrayTimeZoneRule t1"); 
1447     b1 
= t1
->getFinalStart(0, 0, d1
); 
1448     if (!b1 
|| d1 
!= trtimes1
[0]) { 
1449         errln("FAIL: Bad final start time returned from TimeArrayTimeZoneRule t1"); 
1451     b1 
= t4
->getFirstStart(-4*HOUR
, 1*HOUR
, d1
); 
1452     if (!b1 
|| d1 
!= (trtimes1
[0] + 4*HOUR
)) { 
1453         errln("FAIL: Bad first start time returned from TimeArrayTimeZoneRule t4"); 
1455     b1 
= t5
->getFirstStart(-4*HOUR
, 1*HOUR
, d1
); 
1456     if (!b1 
|| d1 
!= (trtimes1
[0] + 3*HOUR
)) { 
1457         errln("FAIL: Bad first start time returned from TimeArrayTimeZoneRule t5"); 
1460     // TimeArrayTimeZoneRule::getNextStart/getPreviousStart 
1461     b1 
= t3
->getNextStart(time1
, -3*HOUR
, 1*HOUR
, FALSE
, d1
); 
1463         dataerrln("FAIL: getNextStart returned TRUE after the final transition for t3"); 
1465     b1 
= t3
->getPreviousStart(time1
, -3*HOUR
, 1*HOUR
, FALSE
, d1
); 
1466     if (!b1 
|| d1 
!= trtimes2
[1]) { 
1467         dataerrln("FAIL: Bad start time returned by getPreviousStart for t3"); 
1469         b2 
= t3
->getPreviousStart(d1
, -3*HOUR
, 1*HOUR
, FALSE
, d2
); 
1470         if (!b2 
|| d2 
!= trtimes2
[0]) { 
1471             errln("FAIL: Bad start time returned by getPreviousStart for t3"); 
1474     b1 
= t3
->getPreviousStart(time3
, -3*HOUR
, 1*HOUR
, FALSE
, d1
); //time3 - year 1950, no result expected 
1476         errln("FAIL: getPreviousStart returned TRUE before the first transition for t3"); 
1479     // TimeArrayTimeZoneRule::isEquivalentTo 
1480     if (!t1
->isEquivalentTo(*t2
)) { 
1481         errln("FAIL: TimeArrayTimeZoneRule t1 is equivalent to t2, but returned FALSE"); 
1483     if (t1
->isEquivalentTo(*t3
)) { 
1484         errln("FAIL: TimeArrayTimeZoneRule t1 is not equivalent to t3, but returned TRUE"); 
1486     if (t1
->isEquivalentTo(*t4
)) { 
1487         errln("FAIL: TimeArrayTimeZoneRule t1 is not equivalent to t4, but returned TRUE"); 
1489     if (t1
->isEquivalentTo(*a1
)) { 
1490         errln("FAIL: TimeArrayTimeZoneRule is not equivalent to AnnualTimeZoneRule, but returned TRUE"); 
1511  * API coverage test for BasicTimeZone APIs in SimpleTimeZone 
1514 TimeZoneRuleTest::TestSimpleTimeZoneCoverage(void) { 
1515     UDate time1 
= getUTCMillis(1990, UCAL_JUNE
, 1); 
1516     UDate time2 
= getUTCMillis(2000, UCAL_JUNE
, 1); 
1518     TimeZoneTransition tzt1
, tzt2
; 
1519     UBool avail1
, avail2
; 
1520     UErrorCode status 
= U_ZERO_ERROR
; 
1521     const TimeZoneRule 
*trrules
[2]; 
1522     const InitialTimeZoneRule 
*ir 
= NULL
; 
1525     // BasicTimeZone API implementation in SimpleTimeZone 
1526     SimpleTimeZone 
*stz1 
= new SimpleTimeZone(-5*HOUR
, "GMT-5"); 
1528     avail1 
= stz1
->getNextTransition(time1
, FALSE
, tzt1
); 
1530         errln("FAIL: No transition must be returned by getNextTranstion for SimpleTimeZone with no DST rule"); 
1532     avail1 
= stz1
->getPreviousTransition(time1
, FALSE
, tzt1
); 
1534         errln("FAIL: No transition must be returned by getPreviousTransition  for SimpleTimeZone with no DST rule"); 
1537     numTzRules 
= stz1
->countTransitionRules(status
); 
1538     if (U_FAILURE(status
)) { 
1539         errln("FAIL: countTransitionRules failed"); 
1541     if (numTzRules 
!= 0) { 
1542         errln((UnicodeString
)"FAIL: countTransitionRules returned " + numTzRules
); 
1545     stz1
->getTimeZoneRules(ir
, trrules
, numTzRules
, status
); 
1546     if (U_FAILURE(status
)) { 
1547         errln("FAIL: getTimeZoneRules failed"); 
1549     if (numTzRules 
!= 0) { 
1550         errln("FAIL: Incorrect transition rule count"); 
1552     if (ir 
== NULL 
|| ir
->getRawOffset() != stz1
->getRawOffset()) { 
1553         errln("FAIL: Bad initial time zone rule"); 
1557     stz1
->setStartRule(UCAL_MARCH
, 11, 2*HOUR
, status
); // March 11 
1558     stz1
->setEndRule(UCAL_NOVEMBER
, 1, UCAL_SUNDAY
, 2*HOUR
, status
); // First Sunday in November 
1559     if (U_FAILURE(status
)) { 
1560         errln("FAIL: Failed to set DST rules in a SimpleTimeZone"); 
1563     avail1 
= stz1
->getNextTransition(time1
, FALSE
, tzt1
); 
1565         errln("FAIL: Non-null transition must be returned by getNextTranstion for SimpleTimeZone with a DST rule"); 
1567     avail1 
= stz1
->getPreviousTransition(time1
, FALSE
, tzt1
); 
1569         errln("FAIL: Non-null transition must be returned by getPreviousTransition  for SimpleTimeZone with a DST rule"); 
1572     numTzRules 
= stz1
->countTransitionRules(status
); 
1573     if (U_FAILURE(status
)) { 
1574         errln("FAIL: countTransitionRules failed"); 
1576     if (numTzRules 
!= 2) { 
1577         errln((UnicodeString
)"FAIL: countTransitionRules returned " + numTzRules
); 
1583     stz1
->getTimeZoneRules(ir
, trrules
, numTzRules
, status
); 
1584     if (U_FAILURE(status
)) { 
1585         errln("FAIL: getTimeZoneRules failed"); 
1587     if (numTzRules 
!= 2) { 
1588         errln("FAIL: Incorrect transition rule count"); 
1590     if (ir 
== NULL 
|| ir
->getRawOffset() != stz1
->getRawOffset()) { 
1591         errln("FAIL: Bad initial time zone rule"); 
1593     if (trrules
[0] == NULL 
|| trrules
[0]->getRawOffset() != stz1
->getRawOffset()) { 
1594         errln("FAIL: Bad transition rule 0"); 
1596     if (trrules
[1] == NULL 
|| trrules
[1]->getRawOffset() != stz1
->getRawOffset()) { 
1597         errln("FAIL: Bad transition rule 1"); 
1600     // Set DST start year 
1601     stz1
->setStartYear(2007); 
1602     avail1 
= stz1
->getPreviousTransition(time1
, FALSE
, tzt1
); 
1604         errln("FAIL: No transition must be returned before 1990"); 
1606     avail1 
= stz1
->getNextTransition(time1
, FALSE
, tzt1
); // transition after 1990-06-01 
1607     avail2 
= stz1
->getNextTransition(time2
, FALSE
, tzt2
); // transition after 2000-06-01 
1608     if (!avail1 
|| !avail2 
|| tzt1 
!= tzt2
) { 
1609         errln("FAIL: Bad transition returned by SimpleTimeZone::getNextTransition"); 
1615  * API coverage test for VTimeZone 
1618 TimeZoneRuleTest::TestVTimeZoneCoverage(void) { 
1619     UErrorCode status 
= U_ZERO_ERROR
; 
1620     UnicodeString 
TZID("Europe/Moscow"); 
1622     BasicTimeZone 
*otz 
= (BasicTimeZone
*)TimeZone::createTimeZone(TZID
); 
1623     VTimeZone 
*vtz 
= VTimeZone::createVTimeZoneByID(TZID
); 
1625     // getOffset(era, year, month, day, dayOfWeek, milliseconds, ec) 
1626     int32_t offset1 
= otz
->getOffset(GregorianCalendar::AD
, 2007, UCAL_JULY
, 1, UCAL_SUNDAY
, 0, status
); 
1627     if (U_FAILURE(status
)) { 
1628         errln("FAIL: getOffset(7 args) failed for otz"); 
1630     int32_t offset2 
= vtz
->getOffset(GregorianCalendar::AD
, 2007, UCAL_JULY
, 1, UCAL_SUNDAY
, 0, status
); 
1631     if (U_FAILURE(status
)) { 
1632         errln("FAIL: getOffset(7 args) failed for vtz"); 
1634     if (offset1 
!= offset2
) { 
1635         errln("FAIL: getOffset(7 args) returned different results in VTimeZone and OlsonTimeZone"); 
1638     // getOffset(era, year, month, day, dayOfWeek, milliseconds, monthLength, ec) 
1639     offset1 
= otz
->getOffset(GregorianCalendar::AD
, 2007, UCAL_JULY
, 1, UCAL_SUNDAY
, 0, 31, status
); 
1640     if (U_FAILURE(status
)) { 
1641         errln("FAIL: getOffset(8 args) failed for otz"); 
1643     offset2 
= vtz
->getOffset(GregorianCalendar::AD
, 2007, UCAL_JULY
, 1, UCAL_SUNDAY
, 0, 31, status
); 
1644     if (U_FAILURE(status
)) { 
1645         errln("FAIL: getOffset(8 args) failed for vtz"); 
1647     if (offset1 
!= offset2
) { 
1648         errln("FAIL: getOffset(8 args) returned different results in VTimeZone and OlsonTimeZone"); 
1652     // getOffset(date, local, rawOffset, dstOffset, ec) 
1653     UDate t 
= Calendar::getNow(); 
1654     int32_t rawOffset1
, dstSavings1
; 
1655     int32_t rawOffset2
, dstSavings2
; 
1657     otz
->getOffset(t
, FALSE
, rawOffset1
, dstSavings1
, status
); 
1658     if (U_FAILURE(status
)) { 
1659         errln("FAIL: getOffset(5 args) failed for otz"); 
1661     vtz
->getOffset(t
, FALSE
, rawOffset2
, dstSavings2
, status
); 
1662     if (U_FAILURE(status
)) { 
1663         errln("FAIL: getOffset(5 args) failed for vtz"); 
1665     if (rawOffset1 
!= rawOffset2 
|| dstSavings1 
!= dstSavings2
) { 
1666         errln("FAIL: getOffset(long,boolean,int[]) returned different results in VTimeZone and OlsonTimeZone"); 
1670     if (otz
->getRawOffset() != vtz
->getRawOffset()) { 
1671         errln("FAIL: getRawOffset returned different results in VTimeZone and OlsonTimeZone"); 
1675     UBool inDst1
, inDst2
; 
1676     inDst1 
= otz
->inDaylightTime(t
, status
); 
1677     if (U_FAILURE(status
)) { 
1678         dataerrln("FAIL: inDaylightTime failed for otz: %s", u_errorName(status
)); 
1680     inDst2 
= vtz
->inDaylightTime(t
, status
); 
1681     if (U_FAILURE(status
)) { 
1682         dataerrln("FAIL: inDaylightTime failed for vtz: %s", u_errorName(status
)); 
1684     if (inDst1 
!= inDst2
) { 
1685         errln("FAIL: inDaylightTime returned different results in VTimeZone and OlsonTimeZone"); 
1689     if (otz
->useDaylightTime() != vtz
->useDaylightTime()) { 
1690         errln("FAIL: useDaylightTime returned different results in VTimeZone and OlsonTimeZone"); 
1694     const int32_t RAW 
= -10*HOUR
; 
1695     VTimeZone 
*tmpvtz 
= (VTimeZone
*)vtz
->clone(); 
1696     tmpvtz
->setRawOffset(RAW
); 
1697     if (tmpvtz
->getRawOffset() != RAW
) { 
1698         logln("setRawOffset is implemented in VTimeZone"); 
1702     UBool bSame 
= otz
->hasSameRules(*vtz
); 
1703     logln((UnicodeString
)"OlsonTimeZone::hasSameRules(VTimeZone) should return FALSE always for now - actual: " + bSame
); 
1705     // getTZURL/setTZURL 
1706     UnicodeString 
TZURL("http://icu-project.org/timezone"); 
1708     if (vtz
->getTZURL(url
)) { 
1709         errln("FAIL: getTZURL returned TRUE"); 
1711     vtz
->setTZURL(TZURL
); 
1712     if (!vtz
->getTZURL(url
) || url 
!= TZURL
) { 
1713         errln("FAIL: URL returned by getTZURL does not match the one set by setTZURL"); 
1716     // getLastModified/setLastModified 
1718     if (vtz
->getLastModified(lastmod
)) { 
1719         errln("FAIL: getLastModified returned TRUE"); 
1721     vtz
->setLastModified(t
); 
1722     if (!vtz
->getLastModified(lastmod
) || lastmod 
!= t
) { 
1723         errln("FAIL: Date returned by getLastModified does not match the one set by setLastModified"); 
1726     // getNextTransition/getPreviousTransition 
1727     UDate base 
= getUTCMillis(2007, UCAL_JULY
, 1); 
1728     TimeZoneTransition tzt1
, tzt2
; 
1729     UBool btr1 
= otz
->getNextTransition(base
, TRUE
, tzt1
); 
1730     UBool btr2 
= vtz
->getNextTransition(base
, TRUE
, tzt2
); 
1731     if (!btr1 
|| !btr2 
|| tzt1 
!= tzt2
) { 
1732         dataerrln("FAIL: getNextTransition returned different results in VTimeZone and OlsonTimeZone"); 
1734     btr1 
= otz
->getPreviousTransition(base
, FALSE
, tzt1
); 
1735     btr2 
= vtz
->getPreviousTransition(base
, FALSE
, tzt2
); 
1736     if (!btr1 
|| !btr2 
|| tzt1 
!= tzt2
) { 
1737         dataerrln("FAIL: getPreviousTransition returned different results in VTimeZone and OlsonTimeZone"); 
1740     // TimeZoneTransition constructor/clone 
1741     TimeZoneTransition 
*tzt1c 
= tzt1
.clone(); 
1742     if (*tzt1c 
!= tzt1 
|| !(*tzt1c 
== tzt1
)) { 
1743         errln("FAIL: TimeZoneTransition tzt1c is equal to tzt1, but got wrong result"); 
1746     TimeZoneTransition 
tzt3(tzt1
); 
1747     if (tzt3 
!= tzt1 
|| !(tzt3 
== tzt1
)) { 
1748         errln("FAIL: TimeZoneTransition tzt3 is equal to tzt1, but got wrong result"); 
1751     // hasEquivalentTransitions 
1752     UDate time1 
= getUTCMillis(1950, UCAL_JANUARY
, 1); 
1753     UDate time2 
= getUTCMillis(2020, UCAL_JANUARY
, 1); 
1754     UBool equiv 
= vtz
->hasEquivalentTransitions(*otz
, time1
, time2
, FALSE
, status
); 
1755     if (U_FAILURE(status
)) { 
1756         dataerrln("FAIL: hasEquivalentTransitions failed for vtz/otz: %s", u_errorName(status
)); 
1759         dataerrln("FAIL: hasEquivalentTransitons returned false for the same time zone"); 
1762     // operator=/operator==/operator!= 
1763     VTimeZone 
*vtz1 
= VTimeZone::createVTimeZoneByID("America/Los_Angeles"); 
1764     if (*vtz1 
== *vtz 
|| !(*vtz1 
!= *vtz
)) { 
1765         errln("FAIL: VTimeZone vtz1 is not equal to vtz, but got wrong result"); 
1768     if (*vtz1 
!= *vtz 
|| !(*vtz1 
== *vtz
)) { 
1769         errln("FAIL: VTimeZone vtz1 is equal to vtz, but got wrong result"); 
1772     // Creation from BasicTimeZone 
1774     status 
= U_ZERO_ERROR
; 
1775     VTimeZone 
*vtzFromBasic 
= NULL
; 
1776     SimpleTimeZone 
*simpleTZ 
= new SimpleTimeZone(28800000, "Asia/Singapore"); 
1777     simpleTZ
->setStartYear(1970); 
1778     simpleTZ
->setStartRule(0,  // month 
1782     simpleTZ
->setEndRule(1, 1, 0, status
); 
1783     if (U_FAILURE(status
)) { 
1784         errln("File %s, line %d, failed with status = %s", __FILE__
, __LINE__
, u_errorName(status
)); 
1785         goto end_basic_tz_test
; 
1787     vtzFromBasic 
= VTimeZone::createVTimeZoneFromBasicTimeZone(*simpleTZ
, status
); 
1788     if (U_FAILURE(status
) || vtzFromBasic 
== NULL
) { 
1789         dataerrln("File %s, line %d, failed with status = %s", __FILE__
, __LINE__
, u_errorName(status
)); 
1790         goto end_basic_tz_test
; 
1793     // delete the source time zone, to make sure there are no dependencies on it. 
1796     // Create another simple time zone w the same rules, and check that it is the 
1797     // same as the test VTimeZone created above. 
1799         SimpleTimeZone 
simpleTZ2(28800000, "Asia/Singapore"); 
1800         simpleTZ2
.setStartYear(1970); 
1801         simpleTZ2
.setStartRule(0,  // month 
1805         simpleTZ2
.setEndRule(1, 1, 0, status
); 
1806         if (U_FAILURE(status
)) { 
1807             errln("File %s, line %d, failed with status = %s", __FILE__
, __LINE__
, u_errorName(status
)); 
1808             goto end_basic_tz_test
; 
1810         if (vtzFromBasic
->hasSameRules(simpleTZ2
) == FALSE
) { 
1811             errln("File %s, line %d, failed hasSameRules() ", __FILE__
, __LINE__
); 
1812             goto end_basic_tz_test
; 
1816     delete vtzFromBasic
; 
1826 TimeZoneRuleTest::TestVTimeZoneParse(void) { 
1827     UErrorCode status 
= U_ZERO_ERROR
; 
1829     // Trying to create VTimeZone from empty data 
1830     UnicodeString emptyData
; 
1831     VTimeZone 
*empty 
= VTimeZone::createVTimeZone(emptyData
, status
); 
1832     if (U_SUCCESS(status
) || empty 
!= NULL
) { 
1834         errln("FAIL: Non-null VTimeZone is returned for empty VTIMEZONE data"); 
1836     status 
= U_ZERO_ERROR
; 
1838     // Create VTimeZone for Asia/Tokyo 
1839     UnicodeString 
asiaTokyoID("Asia/Tokyo"); 
1840     static const UChar asiaTokyo
[] = { 
1841         /* "BEGIN:VTIMEZONE\x0D\x0A" */ 
1842         0x42,0x45,0x47,0x49,0x4E,0x3A,0x56,0x54,0x49,0x4D,0x45,0x5A,0x4F,0x4E,0x45,0x0D,0x0A, 
1843         /* "TZID:Asia\x0D\x0A" */ 
1844         0x54,0x5A,0x49,0x44,0x3A,0x41,0x73,0x69,0x61,0x0D,0x0A, 
1845         /* "\x09/Tokyo\x0D\x0A" */ 
1846         0x09,0x2F,0x54,0x6F,0x6B,0x79,0x6F,0x0D,0x0A, 
1847         /* "BEGIN:STANDARD\x0D\x0A" */ 
1848         0x42,0x45,0x47,0x49,0x4E,0x3A,0x53,0x54,0x41,0x4E,0x44,0x41,0x52,0x44,0x0D,0x0A, 
1849         /* "TZOFFSETFROM:+0900\x0D\x0A" */ 
1850         0x54,0x5A,0x4F,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4F,0x4D,0x3A,0x2B,0x30,0x39,0x30,0x30,0x0D,0x0A, 
1851         /* "TZOFFSETTO:+0900\x0D\x0A" */ 
1852         0x54,0x5A,0x4F,0x46,0x46,0x53,0x45,0x54,0x54,0x4F,0x3A,0x2B,0x30,0x39,0x30,0x30,0x0D,0x0A, 
1853         /* "TZNAME:JST\x0D\x0A" */ 
1854         0x54,0x5A,0x4E,0x41,0x4D,0x45,0x3A,0x4A,0x53,0x54,0x0D,0x0A, 
1855         /* "DTSTART:19700101\x0D\x0A" */ 
1856         0x44,0x54,0x53,0x54,0x41,0x52,0x54,0x3A,0x31,0x39,0x37,0x30,0x30,0x31,0x30,0x31,0x0D,0x0A, 
1857         /* " T000000\x0D\x0A" */ 
1858         0x20,0x54,0x30,0x30,0x30,0x30,0x30,0x30,0x0D,0x0A, 
1859         /* "END:STANDARD\x0D\x0A" */ 
1860         0x45,0x4E,0x44,0x3A,0x53,0x54,0x41,0x4E,0x44,0x41,0x52,0x44,0x0D,0x0A, 
1861         /* "END:VTIMEZONE" */ 
1862         0x45,0x4E,0x44,0x3A,0x56,0x54,0x49,0x4D,0x45,0x5A,0x4F,0x4E,0x45, 
1865     VTimeZone 
*tokyo 
= VTimeZone::createVTimeZone(asiaTokyo
, status
); 
1866     if (U_FAILURE(status
) || tokyo 
== NULL
) { 
1867         errln("FAIL: Failed to create a VTimeZone tokyo"); 
1872         if (tzid 
!= asiaTokyoID
) { 
1873             errln((UnicodeString
)"FAIL: Invalid TZID: " + tzid
); 
1875         // Make sure offsets are correct 
1876         int32_t rawOffset
, dstSavings
; 
1877         tokyo
->getOffset(Calendar::getNow(), FALSE
, rawOffset
, dstSavings
, status
); 
1878         if (U_FAILURE(status
)) { 
1879             errln("FAIL: getOffset failed for tokyo"); 
1881         if (rawOffset 
!= 9*HOUR 
|| dstSavings 
!= 0) { 
1882             errln("FAIL: Bad offsets returned by a VTimeZone created for Tokyo"); 
1887         // Create VTimeZone from VTIMEZONE data 
1888     static const UChar fooData
[] = { 
1889         /* "BEGIN:VCALENDAR\x0D\x0A" */ 
1890         0x42,0x45,0x47,0x49,0x4E,0x3A,0x56,0x43,0x41,0x4C,0x45,0x4E,0x44,0x41,0x52,0x0D,0x0A, 
1891         /* "BEGIN:VTIMEZONE\x0D\x0A" */ 
1892         0x42,0x45,0x47,0x49,0x4E,0x3A,0x56,0x54,0x49,0x4D,0x45,0x5A,0x4F,0x4E,0x45,0x0D,0x0A, 
1893         /* "TZID:FOO\x0D\x0A" */ 
1894         0x54,0x5A,0x49,0x44,0x3A,0x46,0x4F,0x4F,0x0D,0x0A, 
1895         /* "BEGIN:STANDARD\x0D\x0A" */ 
1896         0x42,0x45,0x47,0x49,0x4E,0x3A,0x53,0x54,0x41,0x4E,0x44,0x41,0x52,0x44,0x0D,0x0A, 
1897         /* "TZOFFSETFROM:-0700\x0D\x0A" */ 
1898         0x54,0x5A,0x4F,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4F,0x4D,0x3A,0x2D,0x30,0x37,0x30,0x30,0x0D,0x0A, 
1899         /* "TZOFFSETTO:-0800\x0D\x0A" */ 
1900         0x54,0x5A,0x4F,0x46,0x46,0x53,0x45,0x54,0x54,0x4F,0x3A,0x2D,0x30,0x38,0x30,0x30,0x0D,0x0A, 
1901         /* "TZNAME:FST\x0D\x0A" */ 
1902         0x54,0x5A,0x4E,0x41,0x4D,0x45,0x3A,0x46,0x53,0x54,0x0D,0x0A, 
1903         /* "DTSTART:20071010T010000\x0D\x0A" */ 
1904         0x44,0x54,0x53,0x54,0x41,0x52,0x54,0x3A,0x32,0x30,0x30,0x37,0x31,0x30,0x31,0x30,0x54,0x30,0x31,0x30,0x30,0x30,0x30,0x0D,0x0A, 
1905         /* "RRULE:FREQ=YEARLY;BYDAY=WE;BYMONTHDAY=10,11,12,13,14,15,16;BYMONTH=10\x0D\x0A" */ 
1906         0x52,0x52,0x55,0x4C,0x45,0x3A,0x46,0x52,0x45,0x51,0x3D,0x59,0x45,0x41,0x52,0x4C,0x59,0x3B,0x42,0x59,0x44,0x41,0x59,0x3D,0x57,0x45,0x3B,0x42,0x59,0x4D,0x4F,0x4E,0x54,0x48,0x44,0x41,0x59,0x3D,0x31,0x30,0x2C,0x31,0x31,0x2C,0x31,0x32,0x2C,0x31,0x33,0x2C,0x31,0x34,0x2C,0x31,0x35,0x2C,0x31,0x36,0x3B,0x42,0x59,0x4D,0x4F,0x4E,0x54,0x48,0x3D,0x31,0x30,0x0D,0x0A, 
1907         /* "END:STANDARD\x0D\x0A" */ 
1908         0x45,0x4E,0x44,0x3A,0x53,0x54,0x41,0x4E,0x44,0x41,0x52,0x44,0x0D,0x0A, 
1909         /* "BEGIN:DAYLIGHT\x0D\x0A" */ 
1910         0x42,0x45,0x47,0x49,0x4E,0x3A,0x44,0x41,0x59,0x4C,0x49,0x47,0x48,0x54,0x0D,0x0A, 
1911         /* "TZOFFSETFROM:-0800\x0D\x0A" */ 
1912         0x54,0x5A,0x4F,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4F,0x4D,0x3A,0x2D,0x30,0x38,0x30,0x30,0x0D,0x0A, 
1913         /* "TZOFFSETTO:-0700\x0D\x0A" */ 
1914         0x54,0x5A,0x4F,0x46,0x46,0x53,0x45,0x54,0x54,0x4F,0x3A,0x2D,0x30,0x37,0x30,0x30,0x0D,0x0A, 
1915         /* "TZNAME:FDT\x0D\x0A" */ 
1916         0x54,0x5A,0x4E,0x41,0x4D,0x45,0x3A,0x46,0x44,0x54,0x0D,0x0A, 
1917         /* "DTSTART:20070415T010000\x0D\x0A" */ 
1918         0x44,0x54,0x53,0x54,0x41,0x52,0x54,0x3A,0x32,0x30,0x30,0x37,0x30,0x34,0x31,0x35,0x54,0x30,0x31,0x30,0x30,0x30,0x30,0x0D,0x0A, 
1919         /* "RRULE:FREQ=YEARLY;BYMONTHDAY=15;BYMONTH=4\x0D\x0A" */ 
1920         0x52,0x52,0x55,0x4C,0x45,0x3A,0x46,0x52,0x45,0x51,0x3D,0x59,0x45,0x41,0x52,0x4C,0x59,0x3B,0x42,0x59,0x4D,0x4F,0x4E,0x54,0x48,0x44,0x41,0x59,0x3D,0x31,0x35,0x3B,0x42,0x59,0x4D,0x4F,0x4E,0x54,0x48,0x3D,0x34,0x0D,0x0A, 
1921         /* "END:DAYLIGHT\x0D\x0A" */ 
1922         0x45,0x4E,0x44,0x3A,0x44,0x41,0x59,0x4C,0x49,0x47,0x48,0x54,0x0D,0x0A, 
1923         /* "END:VTIMEZONE\x0D\x0A" */ 
1924         0x45,0x4E,0x44,0x3A,0x56,0x54,0x49,0x4D,0x45,0x5A,0x4F,0x4E,0x45,0x0D,0x0A, 
1925         /* "END:VCALENDAR" */ 
1926         0x45,0x4E,0x44,0x3A,0x56,0x43,0x41,0x4C,0x45,0x4E,0x44,0x41,0x52, 
1930     VTimeZone 
*foo 
= VTimeZone::createVTimeZone(fooData
, status
); 
1931     if (U_FAILURE(status
) || foo 
== NULL
) { 
1932         errln("FAIL: Failed to create a VTimeZone foo"); 
1934         // Write VTIMEZONE data 
1935         UnicodeString fooData2
; 
1936         foo
->write(getUTCMillis(2005, UCAL_JANUARY
, 1), fooData2
, status
); 
1937         if (U_FAILURE(status
)) { 
1938             errln("FAIL: Failed to write VTIMEZONE data for foo"); 
1946 TimeZoneRuleTest::TestT6216(void) { 
1947     // Test case in #6216 
1948     static const UChar tokyoTZ
[] = { 
1949         /* "BEGIN:VCALENDAR\r\n" */ 
1950         0x42,0x45,0x47,0x49,0x4e,0x3a,0x56,0x43,0x41,0x4c,0x45,0x4e,0x44,0x41,0x52,0x0d,0x0a, 
1951         /* "VERSION:2.0\r\n" */ 
1952         0x56,0x45,0x52,0x53,0x49,0x4f,0x4e,0x3a,0x32,0x2e,0x30,0x0d,0x0a, 
1953         /* "PRODID:-//PYVOBJECT//NONSGML Version 1//EN\r\n" */ 
1954         0x50,0x52,0x4f,0x44,0x49,0x44,0x3a,0x2d,0x2f,0x2f,0x50,0x59,0x56,0x4f,0x42,0x4a,0x45,0x43,0x54,0x2f,0x2f,0x4e,0x4f,0x4e,0x53,0x47,0x4d,0x4c,0x20,0x56,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x31,0x2f,0x2f,0x45,0x4e,0x0d,0x0a, 
1955         /* "BEGIN:VTIMEZONE\r\n" */ 
1956         0x42,0x45,0x47,0x49,0x4e,0x3a,0x56,0x54,0x49,0x4d,0x45,0x5a,0x4f,0x4e,0x45,0x0d,0x0a, 
1957         /* "TZID:Asia/Tokyo\r\n" */ 
1958         0x54,0x5a,0x49,0x44,0x3a,0x41,0x73,0x69,0x61,0x2f,0x54,0x6f,0x6b,0x79,0x6f,0x0d,0x0a, 
1959         /* "BEGIN:STANDARD\r\n" */ 
1960         0x42,0x45,0x47,0x49,0x4e,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a, 
1961         /* "DTSTART:20000101T000000\r\n" */ 
1962         0x44,0x54,0x53,0x54,0x41,0x52,0x54,0x3a,0x32,0x30,0x30,0x30,0x30,0x31,0x30,0x31,0x54,0x30,0x30,0x30,0x30,0x30,0x30,0x0d,0x0a, 
1963         /* "RRULE:FREQ=YEARLY;BYMONTH=1\r\n" */ 
1964         0x52,0x52,0x55,0x4c,0x45,0x3a,0x46,0x52,0x45,0x51,0x3d,0x59,0x45,0x41,0x52,0x4c,0x59,0x3b,0x42,0x59,0x4d,0x4f,0x4e,0x54,0x48,0x3d,0x31,0x0d,0x0a, 
1965         /* "TZNAME:Asia/Tokyo\r\n" */ 
1966         0x54,0x5a,0x4e,0x41,0x4d,0x45,0x3a,0x41,0x73,0x69,0x61,0x2f,0x54,0x6f,0x6b,0x79,0x6f,0x0d,0x0a, 
1967         /* "TZOFFSETFROM:+0900\r\n" */ 
1968         0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4f,0x4d,0x3a,0x2b,0x30,0x39,0x30,0x30,0x0d,0x0a, 
1969         /* "TZOFFSETTO:+0900\r\n" */ 
1970         0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x54,0x4f,0x3a,0x2b,0x30,0x39,0x30,0x30,0x0d,0x0a, 
1971         /* "END:STANDARD\r\n" */ 
1972         0x45,0x4e,0x44,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a, 
1973         /* "END:VTIMEZONE\r\n" */ 
1974         0x45,0x4e,0x44,0x3a,0x56,0x54,0x49,0x4d,0x45,0x5a,0x4f,0x4e,0x45,0x0d,0x0a, 
1975         /* "END:VCALENDAR" */ 
1976         0x45,0x4e,0x44,0x3a,0x56,0x43,0x41,0x4c,0x45,0x4e,0x44,0x41,0x52,0x0d,0x0a, 
1979     // Single final rule, overlapping with another 
1980     static const UChar finalOverlap
[] = { 
1981         /* "BEGIN:VCALENDAR\r\n" */ 
1982         0x42,0x45,0x47,0x49,0x4e,0x3a,0x56,0x43,0x41,0x4c,0x45,0x4e,0x44,0x41,0x52,0x0d,0x0a, 
1983         /* "BEGIN:VTIMEZONE\r\n" */ 
1984         0x42,0x45,0x47,0x49,0x4e,0x3a,0x56,0x54,0x49,0x4d,0x45,0x5a,0x4f,0x4e,0x45,0x0d,0x0a, 
1985         /* "TZID:FinalOverlap\r\n" */ 
1986         0x54,0x5a,0x49,0x44,0x3a,0x46,0x69,0x6e,0x61,0x6c,0x4f,0x76,0x65,0x72,0x6c,0x61,0x70,0x0d,0x0a, 
1987         /* "BEGIN:STANDARD\r\n" */ 
1988         0x42,0x45,0x47,0x49,0x4e,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a, 
1989         /* "TZOFFSETFROM:-0200\r\n" */ 
1990         0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4f,0x4d,0x3a,0x2d,0x30,0x32,0x30,0x30,0x0d,0x0a, 
1991         /* "TZOFFSETTO:-0300\r\n" */ 
1992         0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x54,0x4f,0x3a,0x2d,0x30,0x33,0x30,0x30,0x0d,0x0a, 
1993         /* "TZNAME:STD\r\n" */ 
1994         0x54,0x5a,0x4e,0x41,0x4d,0x45,0x3a,0x53,0x54,0x44,0x0d,0x0a, 
1995         /* "DTSTART:20001029T020000\r\n" */ 
1996         0x44,0x54,0x53,0x54,0x41,0x52,0x54,0x3a,0x32,0x30,0x30,0x30,0x31,0x30,0x32,0x39,0x54,0x30,0x32,0x30,0x30,0x30,0x30,0x0d,0x0a, 
1997         /* "RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10\r\n" */ 
1998         0x52,0x52,0x55,0x4c,0x45,0x3a,0x46,0x52,0x45,0x51,0x3d,0x59,0x45,0x41,0x52,0x4c,0x59,0x3b,0x42,0x59,0x44,0x41,0x59,0x3d,0x2d,0x31,0x53,0x55,0x3b,0x42,0x59,0x4d,0x4f,0x4e,0x54,0x48,0x3d,0x31,0x30,0x0d,0x0a, 
1999         /* "END:STANDARD\r\n" */ 
2000         0x45,0x4e,0x44,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a, 
2001         /* "BEGIN:DAYLIGHT\r\n" */ 
2002         0x42,0x45,0x47,0x49,0x4e,0x3a,0x44,0x41,0x59,0x4c,0x49,0x47,0x48,0x54,0x0d,0x0a, 
2003         /* "TZOFFSETFROM:-0300\r\n" */ 
2004         0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4f,0x4d,0x3a,0x2d,0x30,0x33,0x30,0x30,0x0d,0x0a, 
2005         /* "TZOFFSETTO:-0200\r\n" */ 
2006         0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x54,0x4f,0x3a,0x2d,0x30,0x32,0x30,0x30,0x0d,0x0a, 
2007         /* "TZNAME:DST\r\n" */ 
2008         0x54,0x5a,0x4e,0x41,0x4d,0x45,0x3a,0x44,0x53,0x54,0x0d,0x0a, 
2009         /* "DTSTART:19990404T020000\r\n" */ 
2010         0x44,0x54,0x53,0x54,0x41,0x52,0x54,0x3a,0x31,0x39,0x39,0x39,0x30,0x34,0x30,0x34,0x54,0x30,0x32,0x30,0x30,0x30,0x30,0x0d,0x0a, 
2011         /* "RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4;UNTIL=20050403T040000Z\r\n" */ 
2012         0x52,0x52,0x55,0x4c,0x45,0x3a,0x46,0x52,0x45,0x51,0x3d,0x59,0x45,0x41,0x52,0x4c,0x59,0x3b,0x42,0x59,0x44,0x41,0x59,0x3d,0x31,0x53,0x55,0x3b,0x42,0x59,0x4d,0x4f,0x4e,0x54,0x48,0x3d,0x34,0x3b,0x55,0x4e,0x54,0x49,0x4c,0x3d,0x32,0x30,0x30,0x35,0x30,0x34,0x30,0x33,0x54,0x30,0x34,0x30,0x30,0x30,0x30,0x5a,0x0d,0x0a, 
2013         /* "END:DAYLIGHT\r\n" */ 
2014         0x45,0x4e,0x44,0x3a,0x44,0x41,0x59,0x4c,0x49,0x47,0x48,0x54,0x0d,0x0a, 
2015         /* "END:VTIMEZONE\r\n" */ 
2016         0x45,0x4e,0x44,0x3a,0x56,0x54,0x49,0x4d,0x45,0x5a,0x4f,0x4e,0x45,0x0d,0x0a, 
2017         /* "END:VCALENDAR" */ 
2018         0x45,0x4e,0x44,0x3a,0x56,0x43,0x41,0x4c,0x45,0x4e,0x44,0x41,0x52,0x0d,0x0a, 
2021     // Single final rule, no overlapping with another 
2022     static const UChar finalNonOverlap
[] = { 
2023         /* "BEGIN:VCALENDAR\r\n" */ 
2024         0x42,0x45,0x47,0x49,0x4e,0x3a,0x56,0x43,0x41,0x4c,0x45,0x4e,0x44,0x41,0x52,0x0d,0x0a, 
2025         /* "BEGIN:VTIMEZONE\r\n" */ 
2026         0x42,0x45,0x47,0x49,0x4e,0x3a,0x56,0x54,0x49,0x4d,0x45,0x5a,0x4f,0x4e,0x45,0x0d,0x0a, 
2027         /* "TZID:FinalNonOverlap\r\n" */ 
2028         0x54,0x5a,0x49,0x44,0x3a,0x46,0x69,0x6e,0x61,0x6c,0x4e,0x6f,0x6e,0x4f,0x76,0x65,0x72,0x6c,0x61,0x70,0x0d,0x0a, 
2029         /* "BEGIN:STANDARD\r\n" */ 
2030         0x42,0x45,0x47,0x49,0x4e,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a, 
2031         /* "TZOFFSETFROM:-0200\r\n" */ 
2032         0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4f,0x4d,0x3a,0x2d,0x30,0x32,0x30,0x30,0x0d,0x0a, 
2033         /* "TZOFFSETTO:-0300\r\n" */ 
2034         0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x54,0x4f,0x3a,0x2d,0x30,0x33,0x30,0x30,0x0d,0x0a, 
2035         /* "TZNAME:STD\r\n" */ 
2036         0x54,0x5a,0x4e,0x41,0x4d,0x45,0x3a,0x53,0x54,0x44,0x0d,0x0a, 
2037         /* "DTSTART:20001029T020000\r\n" */ 
2038         0x44,0x54,0x53,0x54,0x41,0x52,0x54,0x3a,0x32,0x30,0x30,0x30,0x31,0x30,0x32,0x39,0x54,0x30,0x32,0x30,0x30,0x30,0x30,0x0d,0x0a, 
2039         /* "RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10;UNTIL=20041031T040000Z\r\n" */ 
2040         0x52,0x52,0x55,0x4c,0x45,0x3a,0x46,0x52,0x45,0x51,0x3d,0x59,0x45,0x41,0x52,0x4c,0x59,0x3b,0x42,0x59,0x44,0x41,0x59,0x3d,0x2d,0x31,0x53,0x55,0x3b,0x42,0x59,0x4d,0x4f,0x4e,0x54,0x48,0x3d,0x31,0x30,0x3b,0x55,0x4e,0x54,0x49,0x4c,0x3d,0x32,0x30,0x30,0x34,0x31,0x30,0x33,0x31,0x54,0x30,0x34,0x30,0x30,0x30,0x30,0x5a,0x0d,0x0a, 
2041         /* "END:STANDARD\r\n" */ 
2042         0x45,0x4e,0x44,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a, 
2043         /* "BEGIN:DAYLIGHT\r\n" */ 
2044         0x42,0x45,0x47,0x49,0x4e,0x3a,0x44,0x41,0x59,0x4c,0x49,0x47,0x48,0x54,0x0d,0x0a, 
2045         /* "TZOFFSETFROM:-0300\r\n" */ 
2046         0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4f,0x4d,0x3a,0x2d,0x30,0x33,0x30,0x30,0x0d,0x0a, 
2047         /* "TZOFFSETTO:-0200\r\n" */ 
2048         0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x54,0x4f,0x3a,0x2d,0x30,0x32,0x30,0x30,0x0d,0x0a, 
2049         /* "TZNAME:DST\r\n" */ 
2050         0x54,0x5a,0x4e,0x41,0x4d,0x45,0x3a,0x44,0x53,0x54,0x0d,0x0a, 
2051         /* "DTSTART:19990404T020000\r\n" */ 
2052         0x44,0x54,0x53,0x54,0x41,0x52,0x54,0x3a,0x31,0x39,0x39,0x39,0x30,0x34,0x30,0x34,0x54,0x30,0x32,0x30,0x30,0x30,0x30,0x0d,0x0a, 
2053         /* "RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4;UNTIL=20050403T040000Z\r\n" */ 
2054         0x52,0x52,0x55,0x4c,0x45,0x3a,0x46,0x52,0x45,0x51,0x3d,0x59,0x45,0x41,0x52,0x4c,0x59,0x3b,0x42,0x59,0x44,0x41,0x59,0x3d,0x31,0x53,0x55,0x3b,0x42,0x59,0x4d,0x4f,0x4e,0x54,0x48,0x3d,0x34,0x3b,0x55,0x4e,0x54,0x49,0x4c,0x3d,0x32,0x30,0x30,0x35,0x30,0x34,0x30,0x33,0x54,0x30,0x34,0x30,0x30,0x30,0x30,0x5a,0x0d,0x0a, 
2055         /* "END:DAYLIGHT\r\n" */ 
2056         0x45,0x4e,0x44,0x3a,0x44,0x41,0x59,0x4c,0x49,0x47,0x48,0x54,0x0d,0x0a, 
2057         /* "BEGIN:STANDARD\r\n" */ 
2058         0x42,0x45,0x47,0x49,0x4e,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a, 
2059         /* "TZOFFSETFROM:-0200\r\n" */ 
2060         0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4f,0x4d,0x3a,0x2d,0x30,0x32,0x30,0x30,0x0d,0x0a, 
2061         /* "TZOFFSETTO:-0300\r\n" */ 
2062         0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x54,0x4f,0x3a,0x2d,0x30,0x33,0x30,0x30,0x0d,0x0a, 
2063         /* "TZNAME:STDFINAL\r\n" */ 
2064         0x54,0x5a,0x4e,0x41,0x4d,0x45,0x3a,0x53,0x54,0x44,0x46,0x49,0x4e,0x41,0x4c,0x0d,0x0a, 
2065         /* "DTSTART:20071028T020000\r\n" */ 
2066         0x44,0x54,0x53,0x54,0x41,0x52,0x54,0x3a,0x32,0x30,0x30,0x37,0x31,0x30,0x32,0x38,0x54,0x30,0x32,0x30,0x30,0x30,0x30,0x0d,0x0a, 
2067         /* "RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10\r\n" */ 
2068         0x52,0x52,0x55,0x4c,0x45,0x3a,0x46,0x52,0x45,0x51,0x3d,0x59,0x45,0x41,0x52,0x4c,0x59,0x3b,0x42,0x59,0x44,0x41,0x59,0x3d,0x2d,0x31,0x53,0x55,0x3b,0x42,0x59,0x4d,0x4f,0x4e,0x54,0x48,0x3d,0x31,0x30,0x0d,0x0a, 
2069         /* "END:STANDARD\r\n" */ 
2070         0x45,0x4e,0x44,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a, 
2071         /* "END:VTIMEZONE\r\n" */ 
2072         0x45,0x4e,0x44,0x3a,0x56,0x54,0x49,0x4d,0x45,0x5a,0x4f,0x4e,0x45,0x0d,0x0a, 
2073         /* "END:VCALENDAR" */ 
2074         0x45,0x4e,0x44,0x3a,0x56,0x43,0x41,0x4c,0x45,0x4e,0x44,0x41,0x52,0x0d,0x0a, 
2078     static const int32_t TestDates
[][3] = { 
2079         {1995, UCAL_JANUARY
, 1}, 
2080         {1995, UCAL_JULY
, 1}, 
2081         {2000, UCAL_JANUARY
, 1}, 
2082         {2000, UCAL_JULY
, 1}, 
2083         {2005, UCAL_JANUARY
, 1}, 
2084         {2005, UCAL_JULY
, 1}, 
2085         {2010, UCAL_JANUARY
, 1}, 
2086         {2010, UCAL_JULY
, 1}, 
2090     /*static*/ const UnicodeString TestZones
[] = { 
2091         UnicodeString(tokyoTZ
), 
2092         UnicodeString(finalOverlap
), 
2093         UnicodeString(finalNonOverlap
), 
2097     int32_t Expected
[][8] = { 
2098       //  JAN90      JUL90      JAN00      JUL00      JAN05      JUL05      JAN10      JUL10 
2099         { 32400000,  32400000,  32400000,  32400000,  32400000,  32400000,  32400000,  32400000}, 
2100         {-10800000, -10800000,  -7200000,  -7200000, -10800000,  -7200000, -10800000, -10800000}, 
2101         {-10800000, -10800000,  -7200000,  -7200000, -10800000,  -7200000, -10800000, -10800000} 
2107     UDate times
[UPRV_LENGTHOF(TestDates
)]; 
2110     UErrorCode status 
= U_ZERO_ERROR
; 
2111     TimeZone 
*utc 
= TimeZone::createTimeZone("Etc/GMT"); 
2112     GregorianCalendar 
cal(utc
, status
); 
2113     if (U_FAILURE(status
)) { 
2114         dataerrln("FAIL: Failed to creat a GregorianCalendar: %s", u_errorName(status
)); 
2117     for (i 
= 0; TestDates
[i
][2] != 0; i
++) { 
2119         cal
.set(TestDates
[i
][0], TestDates
[i
][1], TestDates
[i
][2]); 
2120         times
[i
] = cal
.getTime(status
); 
2121         if (U_FAILURE(status
)) { 
2122             errln("FAIL: getTime failed"); 
2129     for (i 
= 0; !TestZones
[i
].isEmpty(); i
++) { 
2130         VTimeZone 
*vtz 
= VTimeZone::createVTimeZone(TestZones
[i
], status
); 
2131         if (U_FAILURE(status
)) { 
2132             errln("FAIL: failed to create VTimeZone"); 
2135         for (j 
= 0; j 
< numTimes
; j
++) { 
2137             status 
= U_ZERO_ERROR
; 
2138             vtz
->getOffset(times
[j
], FALSE
, raw
, dst
, status
); 
2139             if (U_FAILURE(status
)) { 
2140                 errln((UnicodeString
)"FAIL: getOffset failed for time zone " + i 
+ " at " + times
[j
]); 
2142             int32_t offset 
= raw 
+ dst
; 
2143             if (offset 
!= Expected
[i
][j
]) { 
2144                 errln((UnicodeString
)"FAIL: Invalid offset at time(" + times
[j
] + "):" + offset 
+ " Expected:" + Expected
[i
][j
]); 
2152 TimeZoneRuleTest::TestT6669(void) { 
2153     UErrorCode status 
= U_ZERO_ERROR
; 
2154     SimpleTimeZone 
stz(0, "CustomID", UCAL_JANUARY
, 1, UCAL_SUNDAY
, 0, UCAL_JULY
, 1, UCAL_SUNDAY
, 0, status
); 
2155     if (U_FAILURE(status
)) { 
2156         errln("FAIL: Failed to creat a SimpleTimeZone"); 
2160     UDate t 
= 1230681600000.0; //2008-12-31T00:00:00 
2161     UDate expectedNext 
= 1231027200000.0; //2009-01-04T00:00:00 
2162     UDate expectedPrev 
= 1215298800000.0; //2008-07-06T00:00:00 
2164     TimeZoneTransition tzt
; 
2165     UBool avail 
= stz
.getNextTransition(t
, FALSE
, tzt
); 
2167         errln("FAIL: No transition returned by getNextTransition."); 
2168     } else if (tzt
.getTime() != expectedNext
) { 
2169         errln((UnicodeString
)"FAIL: Wrong transition time returned by getNextTransition - " 
2170             + tzt
.getTime() + " Expected: " + expectedNext
); 
2173     avail 
= stz
.getPreviousTransition(t
, TRUE
, tzt
); 
2175         errln("FAIL: No transition returned by getPreviousTransition."); 
2176     } else if (tzt
.getTime() != expectedPrev
) { 
2177         errln((UnicodeString
)"FAIL: Wrong transition time returned by getPreviousTransition - " 
2178             + tzt
.getTime() + " Expected: " + expectedPrev
); 
2183 TimeZoneRuleTest::TestVTimeZoneWrapper(void) { 
2187     UChar 
* data 
= NULL
; 
2191     UDate base 
= 1231027200000.0; //2009-01-04T00:00:00 
2194     const char *name 
= "Test Initial"; 
2208     uprv_memset(uname
, 0, sizeof(uname
)); 
2209     u_uastrcpy(uname
, name
); 
2212     ir1 
= izrule_open(uname
, 13, 2*HOUR
, 0); 
2213     ir2 
= izrule_clone(ir1
); 
2216     b 
= izrule_equals(ir1
, ir2
); 
2217     b 
= izrule_isEquivalentTo(ir1
, ir2
); 
2220     izrule_getName(ir1
, data
, length
); 
2221     i 
= izrule_getRawOffset(ir1
); 
2222     i 
= izrule_getDSTSavings(ir1
); 
2224     b 
= izrule_getFirstStart(ir1
, 2*HOUR
, 0, result
); 
2225     b 
= izrule_getFinalStart(ir1
, 2*HOUR
, 0, result
); 
2226     b 
= izrule_getNextStart(ir1
, base 
, 2*HOUR
, 0, true, result
); 
2227     b 
= izrule_getPreviousStart(ir1
, base
, 2*HOUR
, 0, true, result
); 
2230     cid1 
= izrule_getStaticClassID(ir1
); 
2231     cid2 
= izrule_getDynamicClassID(ir1
); 
2234     zt1 
= ztrans_open(base
, ir1
, ir2
); 
2235     zt2 
= ztrans_clone(zt1
); 
2236     zt2 
= ztrans_openEmpty(); 
2239     b 
= ztrans_equals(zt1
, zt2
); 
2242     result 
= ztrans_getTime(zt1
); 
2243     ztrans_setTime(zt1
, result
); 
2245     r 
= (ZRule
*)ztrans_getFrom(zt1
); 
2246     ztrans_setFrom(zt1
, (void*)ir1
); 
2247     ztrans_adoptFrom(zt1
, (void*)ir1
); 
2249     r 
= (ZRule
*)ztrans_getTo(zt1
); 
2250     ztrans_setTo(zt1
, (void*)ir2
); 
2251     ztrans_adoptTo(zt1
, (void*)ir2
); 
2254     cid1 
= ztrans_getStaticClassID(zt1
); 
2255     cid2 
= ztrans_getDynamicClassID(zt2
); 
2258     v1 
= vzone_openID((UChar
*)"America/Chicago", sizeof("America/Chicago")); 
2259     v2 
= vzone_clone(v1
); 
2260     //v2 = vzone_openData(const UChar* vtzdata, int32_t vtzdataLength, UErrorCode& status); 
2263     b 
= vzone_equals(v1
, v2
); 
2264     b 
= vzone_hasSameRules(v1
, v2
); 
2267     b 
= vzone_getTZURL(v1
, data
, length
); 
2268     vzone_setTZURL(v1
, data
, length
); 
2270     b 
= vzone_getLastModified(v1
, result
); 
2271     vzone_setLastModified(v1
, result
); 
2274     vzone_write(v1
, data
, length
, status
); 
2275     vzone_writeFromStart(v1
, result
, data
, length
, status
); 
2276     vzone_writeSimple(v1
, result
, data
, length
, status
); 
2278     // test more accessors 
2279     i 
= vzone_getRawOffset(v1
); 
2280     vzone_setRawOffset(v1
, i
); 
2282     b 
= vzone_useDaylightTime(v1
); 
2283     b 
= vzone_inDaylightTime(v1
, result
, status
); 
2285     b 
= vzone_getNextTransition(v1
, result
, false, zt1
); 
2286     b 
= vzone_getPreviousTransition(v1
, result
, false, zt1
); 
2287     i 
= vzone_countTransitionRules(v1
, status
); 
2289     cid1 
= vzone_getStaticClassID(v1
); 
2290     cid2 
= vzone_getDynamicClassID(v1
); 
2300 //----------- private test helpers ------------------------------------------------- 
2303 TimeZoneRuleTest::getUTCMillis(int32_t y
, int32_t m
, int32_t d
, 
2304                                int32_t hr
, int32_t min
, int32_t sec
, int32_t msec
) { 
2305     UErrorCode status 
= U_ZERO_ERROR
; 
2306     const TimeZone 
*tz 
= TimeZone::getGMT(); 
2307     Calendar 
*cal 
= Calendar::createInstance(*tz
, status
); 
2308     if (U_FAILURE(status
)) { 
2310         dataerrln("FAIL: Calendar::createInstance failed: %s", u_errorName(status
)); 
2313     cal
->set(y
, m
, d
, hr
, min
, sec
); 
2314     cal
->set(UCAL_MILLISECOND
, msec
); 
2315     UDate utc 
= cal
->getTime(status
); 
2316     if (U_FAILURE(status
)) { 
2318         errln("FAIL: Calendar::getTime failed"); 
2326  * Check if a time shift really happens on each transition returned by getNextTransition or 
2327  * getPreviousTransition in the specified time range 
2330 TimeZoneRuleTest::verifyTransitions(BasicTimeZone
& icutz
, UDate start
, UDate end
) { 
2331     UErrorCode status 
= U_ZERO_ERROR
; 
2333     int32_t raw
, dst
, raw0
, dst0
; 
2334     TimeZoneTransition tzt
, tzt0
; 
2342         avail 
= icutz
.getNextTransition(time
, FALSE
, tzt
); 
2346         time 
= tzt
.getTime(); 
2350         icutz
.getOffset(time
, FALSE
, raw
, dst
, status
); 
2351         icutz
.getOffset(time 
- 1, FALSE
, raw0
, dst0
, status
); 
2352         if (U_FAILURE(status
)) { 
2353             errln("FAIL: Error in getOffset"); 
2357         if (raw 
== raw0 
&& dst 
== dst0
) { 
2358             errln((UnicodeString
)"FAIL: False transition returned by getNextTransition for " 
2359                 + icutz
.getID(tzid
) + " at " + dateToString(time
)); 
2362                 (tzt0
.getTo()->getRawOffset() != tzt
.getFrom()->getRawOffset() 
2363                 || tzt0
.getTo()->getDSTSavings() != tzt
.getFrom()->getDSTSavings())) { 
2364             errln((UnicodeString
)"FAIL: TO rule of the previous transition does not match FROM rule of this transtion at " 
2365                     + dateToString(time
) + " for " + icutz
.getID(tzid
));                 
2375         avail 
= icutz
.getPreviousTransition(time
, FALSE
, tzt
); 
2379         time 
= tzt
.getTime(); 
2380         if (time 
<= start
) { 
2383         icutz
.getOffset(time
, FALSE
, raw
, dst
, status
); 
2384         icutz
.getOffset(time 
- 1, FALSE
, raw0
, dst0
, status
); 
2385         if (U_FAILURE(status
)) { 
2386             errln("FAIL: Error in getOffset"); 
2390         if (raw 
== raw0 
&& dst 
== dst0
) { 
2391             errln((UnicodeString
)"FAIL: False transition returned by getPreviousTransition for " 
2392                 + icutz
.getID(tzid
) + " at " + dateToString(time
)); 
2396                 (tzt0
.getFrom()->getRawOffset() != tzt
.getTo()->getRawOffset() 
2397                 || tzt0
.getFrom()->getDSTSavings() != tzt
.getTo()->getDSTSavings())) { 
2398             errln((UnicodeString
)"FAIL: TO rule of the next transition does not match FROM rule in this transtion at " 
2399                     + dateToString(time
) + " for " + icutz
.getID(tzid
));                 
2407  * Compare all time transitions in 2 time zones in the specified time range in ascending order 
2410 TimeZoneRuleTest::compareTransitionsAscending(BasicTimeZone
& z1
, BasicTimeZone
& z2
, 
2411                                               UDate start
, UDate end
, UBool inclusive
) { 
2412     UnicodeString zid1
, zid2
; 
2413     TimeZoneTransition tzt1
, tzt2
; 
2414     UBool avail1
, avail2
; 
2415     UBool inRange1
, inRange2
; 
2422         avail1 
= z1
.getNextTransition(time
, inclusive
, tzt1
); 
2423         avail2 
= z2
.getNextTransition(time
, inclusive
, tzt2
); 
2425         inRange1 
= inRange2 
= FALSE
; 
2427             if (tzt1
.getTime() < end 
|| (inclusive 
&& tzt1
.getTime() == end
)) { 
2432             if (tzt2
.getTime() < end 
|| (inclusive 
&& tzt2
.getTime() == end
)) { 
2436         if (!inRange1 
&& !inRange2
) { 
2437             // No more transition in the range 
2441             errln((UnicodeString
)"FAIL: " + zid1 
+ " does not have any transitions after " 
2442                 + dateToString(time
) + " before " + dateToString(end
)); 
2446             errln((UnicodeString
)"FAIL: " + zid2 
+ " does not have any transitions after " 
2447                 + dateToString(time
) + " before " + dateToString(end
)); 
2450         if (tzt1
.getTime() != tzt2
.getTime()) { 
2451             errln((UnicodeString
)"FAIL: First transition after " + dateToString(time
) + " " 
2452                     + zid1 
+ "[" + dateToString(tzt1
.getTime()) + "] " 
2453                     + zid2 
+ "[" + dateToString(tzt2
.getTime()) + "]"); 
2456         time 
= tzt1
.getTime(); 
2464  * Compare all time transitions in 2 time zones in the specified time range in descending order 
2467 TimeZoneRuleTest::compareTransitionsDescending(BasicTimeZone
& z1
, BasicTimeZone
& z2
, 
2468                                                UDate start
, UDate end
, UBool inclusive
) { 
2469     UnicodeString zid1
, zid2
; 
2470     TimeZoneTransition tzt1
, tzt2
; 
2471     UBool avail1
, avail2
; 
2472     UBool inRange1
, inRange2
; 
2479         avail1 
= z1
.getPreviousTransition(time
, inclusive
, tzt1
); 
2480         avail2 
= z2
.getPreviousTransition(time
, inclusive
, tzt2
); 
2482         inRange1 
= inRange2 
= FALSE
; 
2484             if (tzt1
.getTime() > start 
|| (inclusive 
&& tzt1
.getTime() == start
)) { 
2489             if (tzt2
.getTime() > start 
|| (inclusive 
&& tzt2
.getTime() == start
)) { 
2493         if (!inRange1 
&& !inRange2
) { 
2494             // No more transition in the range 
2498             errln((UnicodeString
)"FAIL: " + zid1 
+ " does not have any transitions before " 
2499                 + dateToString(time
) + " after " + dateToString(start
)); 
2503             errln((UnicodeString
)"FAIL: " + zid2 
+ " does not have any transitions before " 
2504                 + dateToString(time
) + " after " + dateToString(start
)); 
2507         if (tzt1
.getTime() != tzt2
.getTime()) { 
2508             errln((UnicodeString
)"FAIL: Last transition before " + dateToString(time
) + " " 
2509                     + zid1 
+ "[" + dateToString(tzt1
.getTime()) + "] " 
2510                     + zid2 
+ "[" + dateToString(tzt2
.getTime()) + "]"); 
2513         time 
= tzt1
.getTime(); 
2520 // Slightly modified version of BasicTimeZone::hasEquivalentTransitions. 
2521 // This version returns TRUE if transition time delta is within the given 
2523 static UBool 
hasEquivalentTransitions(/*const*/ BasicTimeZone
& tz1
, /*const*/BasicTimeZone
& tz2
, 
2524                                         UDate start
, UDate end
, 
2525                                         UBool ignoreDstAmount
, int32_t maxTransitionTimeDelta
, 
2526                                         UErrorCode
& status
) { 
2527     if (U_FAILURE(status
)) { 
2530     if (tz1
.hasSameRules(tz2
)) { 
2533     // Check the offsets at the start time 
2534     int32_t raw1
, raw2
, dst1
, dst2
; 
2535     tz1
.getOffset(start
, FALSE
, raw1
, dst1
, status
); 
2536     if (U_FAILURE(status
)) { 
2539     tz2
.getOffset(start
, FALSE
, raw2
, dst2
, status
); 
2540     if (U_FAILURE(status
)) { 
2543     if (ignoreDstAmount
) { 
2544         if ((raw1 
+ dst1 
!= raw2 
+ dst2
) 
2545             || (dst1 
!= 0 && dst2 
== 0) 
2546             || (dst1 
== 0 && dst2 
!= 0)) { 
2550         if (raw1 
!= raw2 
|| dst1 
!= dst2
) { 
2554     // Check transitions in the range 
2556     TimeZoneTransition tr1
, tr2
; 
2558         UBool avail1 
= tz1
.getNextTransition(time
, FALSE
, tr1
); 
2559         UBool avail2 
= tz2
.getNextTransition(time
, FALSE
, tr2
); 
2561         if (ignoreDstAmount
) { 
2562             // Skip a transition which only differ the amount of DST savings 
2565                         && tr1
.getTime() <= end
 
2566                         && (tr1
.getFrom()->getRawOffset() + tr1
.getFrom()->getDSTSavings() 
2567                                 == tr1
.getTo()->getRawOffset() + tr1
.getTo()->getDSTSavings()) 
2568                         && (tr1
.getFrom()->getDSTSavings() != 0 && tr1
.getTo()->getDSTSavings() != 0)) { 
2569                     tz1
.getNextTransition(tr1
.getTime(), FALSE
, tr1
); 
2576                         && tr2
.getTime() <= end
 
2577                         && (tr2
.getFrom()->getRawOffset() + tr2
.getFrom()->getDSTSavings() 
2578                                 == tr2
.getTo()->getRawOffset() + tr2
.getTo()->getDSTSavings()) 
2579                         && (tr2
.getFrom()->getDSTSavings() != 0 && tr2
.getTo()->getDSTSavings() != 0)) { 
2580                     tz2
.getNextTransition(tr2
.getTime(), FALSE
, tr2
); 
2587         UBool inRange1 
= (avail1 
&& tr1
.getTime() <= end
); 
2588         UBool inRange2 
= (avail2 
&& tr2
.getTime() <= end
); 
2589         if (!inRange1 
&& !inRange2
) { 
2590             // No more transition in the range 
2593         if (!inRange1 
|| !inRange2
) { 
2596         double delta 
= tr1
.getTime() >= tr2
.getTime() ? tr1
.getTime() - tr2
.getTime() : tr2
.getTime() - tr1
.getTime(); 
2597         if (delta 
> (double)maxTransitionTimeDelta
) { 
2600         if (ignoreDstAmount
) { 
2601             if (tr1
.getTo()->getRawOffset() + tr1
.getTo()->getDSTSavings() 
2602                         != tr2
.getTo()->getRawOffset() + tr2
.getTo()->getDSTSavings() 
2603                     || (tr1
.getTo()->getDSTSavings() != 0 &&  tr2
.getTo()->getDSTSavings() == 0) 
2604                     || (tr1
.getTo()->getDSTSavings() == 0 &&  tr2
.getTo()->getDSTSavings() != 0)) { 
2608             if (tr1
.getTo()->getRawOffset() != tr2
.getTo()->getRawOffset() || 
2609                 tr1
.getTo()->getDSTSavings() != tr2
.getTo()->getDSTSavings()) { 
2613         time 
= tr1
.getTime() > tr2
.getTime() ? tr1
.getTime() : tr2
.getTime(); 
2618 // Test case for ticket#8943 
2619 // RuleBasedTimeZone#getOffsets throws NPE 
2621 TimeZoneRuleTest::TestT8943(void) { 
2622     UErrorCode status 
= U_ZERO_ERROR
; 
2623     UnicodeString 
id("Ekaterinburg Time"); 
2624     UnicodeString 
stdName("Ekaterinburg Standard Time"); 
2625     UnicodeString 
dstName("Ekaterinburg Daylight Time"); 
2627     InitialTimeZoneRule 
*initialRule 
= new InitialTimeZoneRule(stdName
, 18000000, 0); 
2628     RuleBasedTimeZone 
*rbtz 
= new RuleBasedTimeZone(id
, initialRule
); 
2630     DateTimeRule 
*dtRule 
= new DateTimeRule(UCAL_OCTOBER
, -1, UCAL_SUNDAY
, 10800000, DateTimeRule::WALL_TIME
); 
2631     AnnualTimeZoneRule 
*atzRule 
= new AnnualTimeZoneRule(stdName
, 18000000, 0, dtRule
, 2000, 2010); 
2632     rbtz
->addTransitionRule(atzRule
, status
); 
2634     dtRule 
= new DateTimeRule(UCAL_MARCH
, -1, UCAL_SUNDAY
, 7200000, DateTimeRule::WALL_TIME
); 
2635     atzRule 
= new AnnualTimeZoneRule(dstName
, 18000000, 3600000, dtRule
, 2000, 2010); 
2636     rbtz
->addTransitionRule(atzRule
, status
); 
2638     dtRule 
= new DateTimeRule(UCAL_JANUARY
, 1, 0, DateTimeRule::WALL_TIME
); 
2639     atzRule 
= new AnnualTimeZoneRule(stdName
, 21600000, 0, dtRule
, 2011, AnnualTimeZoneRule::MAX_YEAR
); 
2640     rbtz
->addTransitionRule(atzRule
, status
); 
2642     dtRule 
= new DateTimeRule(UCAL_JANUARY
, 1, 1, DateTimeRule::WALL_TIME
); 
2643     atzRule 
= new AnnualTimeZoneRule(dstName
, 21600000, 0, dtRule
, 2011, AnnualTimeZoneRule::MAX_YEAR
); 
2644     rbtz
->addTransitionRule(atzRule
, status
); 
2645     rbtz
->complete(status
); 
2647     if (U_FAILURE(status
)) { 
2648         errln("Failed to construct a RuleBasedTimeZone"); 
2651         rbtz
->getOffset(1293822000000.0 /* 2010-12-31 19:00:00 UTC */, FALSE
, raw
, dst
, status
); 
2652         if (U_FAILURE(status
)) { 
2653             errln("Error invoking getOffset"); 
2654         } else if (raw 
!= 21600000 || dst 
!= 0) { 
2655             errln(UnicodeString("Fail: Wrong offsets: ") + raw 
+ "/" + dst 
+ " Expected: 21600000/0"); 
2662 #endif /* #if !UCONFIG_NO_FORMATTING */