2 *******************************************************************************
3 * Copyright (C) 2007-2008, 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/tztrans.h"
22 #include "unicode/vtzone.h"
25 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
26 #define HOUR (60*60*1000)
28 static const char *const TESTZIDS
[] = {
31 "America/Los_Angeles",
32 "America/Indiana/Indianapolis",
44 class TestZIDEnumeration
: public StringEnumeration
{
46 TestZIDEnumeration(UBool all
= FALSE
);
47 ~TestZIDEnumeration();
49 virtual int32_t count(UErrorCode
& /*status*/) const {
52 virtual const UnicodeString
*snext(UErrorCode
& status
);
53 virtual void reset(UErrorCode
& status
);
54 static inline UClassID
getStaticClassID() {
55 return (UClassID
)&fgClassID
;
57 virtual UClassID
getDynamicClassID() const {
58 return getStaticClassID();
61 static const char fgClassID
;
64 StringEnumeration
*tzenum
;
67 const char TestZIDEnumeration::fgClassID
= 0;
69 TestZIDEnumeration::TestZIDEnumeration(UBool all
)
71 UErrorCode status
= U_ZERO_ERROR
;
73 tzenum
= TimeZone::createEnumeration();
74 len
= tzenum
->count(status
);
77 len
= (int32_t)sizeof(TESTZIDS
)/sizeof(TESTZIDS
[0]);
81 TestZIDEnumeration::~TestZIDEnumeration() {
88 TestZIDEnumeration::snext(UErrorCode
& status
) {
90 return tzenum
->snext(status
);
91 } else if (U_SUCCESS(status
) && idx
< len
) {
92 unistr
= UnicodeString(TESTZIDS
[idx
++], "");
99 TestZIDEnumeration::reset(UErrorCode
& status
) {
100 if (tzenum
!= NULL
) {
101 tzenum
->reset(status
);
108 void TimeZoneRuleTest::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* /*par*/ )
111 logln("TestSuite TestTimeZoneRule");
114 CASE(0, TestSimpleRuleBasedTimeZone
);
115 CASE(1, TestHistoricalRuleBasedTimeZone
);
116 CASE(2, TestOlsonTransition
);
117 CASE(3, TestRBTZTransition
);
118 CASE(4, TestHasEquivalentTransitions
);
119 CASE(5, TestVTimeZoneRoundTrip
);
120 CASE(6, TestVTimeZoneRoundTripPartial
);
121 CASE(7, TestVTimeZoneSimpleWrite
);
122 CASE(8, TestVTimeZoneHeaderProps
);
123 CASE(9, TestGetSimpleRules
);
124 CASE(10, TestTimeZoneRuleCoverage
);
125 CASE(11, TestSimpleTimeZoneCoverage
);
126 CASE(12, TestVTimeZoneCoverage
);
127 CASE(13, TestVTimeZoneParse
);
129 default: name
= ""; break;
134 * Compare SimpleTimeZone with equivalent RBTZ
137 TimeZoneRuleTest::TestSimpleRuleBasedTimeZone(void) {
138 UErrorCode status
= U_ZERO_ERROR
;
139 SimpleTimeZone
stz(-1*HOUR
, "TestSTZ",
140 UCAL_SEPTEMBER
, -30, -UCAL_SATURDAY
, 1*HOUR
, SimpleTimeZone::WALL_TIME
,
141 UCAL_FEBRUARY
, 2, UCAL_SUNDAY
, 1*HOUR
, SimpleTimeZone::WALL_TIME
,
143 if (U_FAILURE(status
)) {
144 errln("FAIL: Couldn't create SimpleTimezone.");
148 AnnualTimeZoneRule
*atzr
;
149 int32_t STARTYEAR
= 2000;
151 InitialTimeZoneRule
*ir
= new InitialTimeZoneRule(
152 "RBTZ_Initial", // Initial time Name
153 -1*HOUR
, // Raw offset
154 1*HOUR
); // DST saving amount
157 RuleBasedTimeZone
*rbtz1
= new RuleBasedTimeZone("RBTZ1", ir
->clone());
158 dtr
= new DateTimeRule(UCAL_SEPTEMBER
, 30, UCAL_SATURDAY
, FALSE
,
159 1*HOUR
, DateTimeRule::WALL_TIME
); // SUN<=30 in September, at 1AM wall time
160 atzr
= new AnnualTimeZoneRule("RBTZ_DST1",
161 -1*HOUR
/*rawOffset*/, 1*HOUR
/*dstSavings*/, dtr
,
162 STARTYEAR
, AnnualTimeZoneRule::MAX_YEAR
);
163 rbtz1
->addTransitionRule(atzr
, status
);
164 if (U_FAILURE(status
)) {
165 errln("FAIL: couldn't add AnnualTimeZoneRule 1-1.");
167 dtr
= new DateTimeRule(UCAL_FEBRUARY
, 2, UCAL_SUNDAY
,
168 1*HOUR
, DateTimeRule::WALL_TIME
); // 2nd Sunday in February, at 1AM wall time
169 atzr
= new AnnualTimeZoneRule("RBTZ_STD1",
170 -1*HOUR
/*rawOffset*/, 0 /*dstSavings*/, dtr
,
171 STARTYEAR
, AnnualTimeZoneRule::MAX_YEAR
);
172 rbtz1
->addTransitionRule(atzr
, status
);
173 if (U_FAILURE(status
)) {
174 errln("FAIL: couldn't add AnnualTimeZoneRule 1-2.");
176 rbtz1
->complete(status
);
177 if (U_FAILURE(status
)) {
178 errln("FAIL: couldn't complete RBTZ 1.");
181 // Equivalent, but different date rule type
182 RuleBasedTimeZone
*rbtz2
= new RuleBasedTimeZone("RBTZ2", ir
->clone());
183 dtr
= new DateTimeRule(UCAL_SEPTEMBER
, -1, UCAL_SATURDAY
,
184 1*HOUR
, DateTimeRule::WALL_TIME
); // Last Sunday in September at 1AM wall time
185 atzr
= new AnnualTimeZoneRule("RBTZ_DST2", -1*HOUR
, 1*HOUR
, dtr
, STARTYEAR
, AnnualTimeZoneRule::MAX_YEAR
);
186 rbtz2
->addTransitionRule(atzr
, status
);
187 if (U_FAILURE(status
)) {
188 errln("FAIL: couldn't add AnnualTimeZoneRule 2-1.");
190 dtr
= new DateTimeRule(UCAL_FEBRUARY
, 8, UCAL_SUNDAY
, true,
191 1*HOUR
, DateTimeRule::WALL_TIME
); // SUN>=8 in February, at 1AM wall time
192 atzr
= new AnnualTimeZoneRule("RBTZ_STD2", -1*HOUR
, 0, dtr
, STARTYEAR
, AnnualTimeZoneRule::MAX_YEAR
);
193 rbtz2
->addTransitionRule(atzr
, status
);
194 if (U_FAILURE(status
)) {
195 errln("FAIL: couldn't add AnnualTimeZoneRule 2-2.");
197 rbtz2
->complete(status
);
198 if (U_FAILURE(status
)) {
199 errln("FAIL: couldn't complete RBTZ 2");
202 // Equivalent, but different time rule type
203 RuleBasedTimeZone
*rbtz3
= new RuleBasedTimeZone("RBTZ3", ir
->clone());
204 dtr
= new DateTimeRule(UCAL_SEPTEMBER
, 30, UCAL_SATURDAY
, false,
205 2*HOUR
, DateTimeRule::UTC_TIME
);
206 atzr
= new AnnualTimeZoneRule("RBTZ_DST3", -1*HOUR
, 1*HOUR
, dtr
, STARTYEAR
, AnnualTimeZoneRule::MAX_YEAR
);
207 rbtz3
->addTransitionRule(atzr
, status
);
208 if (U_FAILURE(status
)) {
209 errln("FAIL: couldn't add AnnualTimeZoneRule 3-1.");
211 dtr
= new DateTimeRule(UCAL_FEBRUARY
, 2, UCAL_SUNDAY
,
212 0*HOUR
, DateTimeRule::STANDARD_TIME
);
213 atzr
= new AnnualTimeZoneRule("RBTZ_STD3", -1*HOUR
, 0, dtr
, STARTYEAR
, AnnualTimeZoneRule::MAX_YEAR
);
214 rbtz3
->addTransitionRule(atzr
, status
);
215 if (U_FAILURE(status
)) {
216 errln("FAIL: couldn't add AnnualTimeZoneRule 3-2.");
218 rbtz3
->complete(status
);
219 if (U_FAILURE(status
)) {
220 errln("FAIL: couldn't complete RBTZ 3");
223 // Check equivalency for 10 years
224 UDate start
= getUTCMillis(STARTYEAR
, UCAL_JANUARY
, 1);
225 UDate until
= getUTCMillis(STARTYEAR
+ 10, UCAL_JANUARY
, 1);
227 if (!(stz
.hasEquivalentTransitions(*rbtz1
, start
, until
, TRUE
, status
))) {
228 errln("FAIL: rbtz1 must be equivalent to the SimpleTimeZone in the time range.");
230 if (U_FAILURE(status
)) {
231 errln("FAIL: error returned from hasEquivalentTransitions");
233 if (!(stz
.hasEquivalentTransitions(*rbtz2
, start
, until
, TRUE
, status
))) {
234 errln("FAIL: rbtz2 must be equivalent to the SimpleTimeZone in the time range.");
236 if (U_FAILURE(status
)) {
237 errln("FAIL: error returned from hasEquivalentTransitions");
239 if (!(stz
.hasEquivalentTransitions(*rbtz3
, start
, until
, TRUE
, status
))) {
240 errln("FAIL: rbtz3 must be equivalent to the SimpleTimeZone in the time range.");
242 if (U_FAILURE(status
)) {
243 errln("FAIL: error returned from hasEquivalentTransitions");
247 if (rbtz1
->hasSameRules(*rbtz2
)) {
248 errln("FAIL: rbtz1 and rbtz2 have different rules, but returned true.");
250 if (rbtz1
->hasSameRules(*rbtz3
)) {
251 errln("FAIL: rbtz1 and rbtz3 have different rules, but returned true.");
253 RuleBasedTimeZone
*rbtz1c
= (RuleBasedTimeZone
*)rbtz1
->clone();
254 if (!rbtz1
->hasSameRules(*rbtz1c
)) {
255 errln("FAIL: Cloned RuleBasedTimeZone must have the same rules with the original.");
259 int32_t era
, year
, month
, dayOfMonth
, dayOfWeek
, millisInDay
;
261 int32_t offset
, dstSavings
;
264 GregorianCalendar
*cal
= new GregorianCalendar(status
);
265 if (U_FAILURE(status
)) {
266 errln("FAIL: Could not create a Gregorian calendar instance.");
268 cal
->setTimeZone(*rbtz1
);
272 cal
->set(UCAL_ERA
, GregorianCalendar::BC
);
273 cal
->set(1000, UCAL_JANUARY
, 1);
275 era
= cal
->get(UCAL_ERA
, status
);
276 year
= cal
->get(UCAL_YEAR
, status
);
277 month
= cal
->get(UCAL_MONTH
, status
);
278 dayOfMonth
= cal
->get(UCAL_DAY_OF_MONTH
, status
);
279 dayOfWeek
= cal
->get(UCAL_DAY_OF_WEEK
, status
);
280 millisInDay
= cal
->get(UCAL_MILLISECONDS_IN_DAY
, status
);
281 time
= cal
->getTime(status
);
282 if (U_FAILURE(status
)) {
283 errln("FAIL: Could not get calendar field values.");
285 offset
= rbtz1
->getOffset(era
, year
, month
, dayOfMonth
, dayOfWeek
, millisInDay
, status
);
286 if (U_FAILURE(status
)) {
287 errln("FAIL: getOffset(7 args) failed.");
290 errln(UnicodeString("FAIL: Invalid time zone offset: ") + offset
+ " /expected: 0");
292 dst
= rbtz1
->inDaylightTime(time
, status
);
293 if (U_FAILURE(status
)) {
294 errln("FAIL: inDaylightTime failed.");
297 errln("FAIL: Invalid daylight saving time");
299 rbtz1
->getOffset(time
, TRUE
, offset
, dstSavings
, status
);
300 if (U_FAILURE(status
)) {
301 errln("FAIL: getOffset(5 args) failed.");
303 if (offset
!= -3600000) {
304 errln(UnicodeString("FAIL: Invalid time zone raw offset: ") + offset
+ " /expected: -3600000");
306 if (dstSavings
!= 3600000) {
307 errln(UnicodeString("FAIL: Invalid DST amount: ") + dstSavings
+ " /expected: 3600000");
311 cal
->set(UCAL_ERA
, GregorianCalendar::AD
);
312 cal
->set(2000, UCAL_JULY
, 1);
314 era
= cal
->get(UCAL_ERA
, status
);
315 year
= cal
->get(UCAL_YEAR
, status
);
316 month
= cal
->get(UCAL_MONTH
, status
);
317 dayOfMonth
= cal
->get(UCAL_DAY_OF_MONTH
, status
);
318 dayOfWeek
= cal
->get(UCAL_DAY_OF_WEEK
, status
);
319 millisInDay
= cal
->get(UCAL_MILLISECONDS_IN_DAY
, status
);
320 time
= cal
->getTime(status
);
321 if (U_FAILURE(status
)) {
322 errln("FAIL: Could not get calendar field values.");
324 offset
= rbtz1
->getOffset(era
, year
, month
, dayOfMonth
, dayOfWeek
, millisInDay
, status
);
325 if (U_FAILURE(status
)) {
326 errln("FAIL: getOffset(7 args) failed.");
328 if (offset
!= -3600000) {
329 errln((UnicodeString
)"FAIL: Invalid time zone offset: " + offset
+ " /expected: -3600000");
331 dst
= rbtz1
->inDaylightTime(time
, status
);
332 if (U_FAILURE(status
)) {
333 errln("FAIL: inDaylightTime failed.");
336 errln("FAIL: Invalid daylight saving time");
338 rbtz1
->getOffset(time
, TRUE
, offset
, dstSavings
, status
);
339 if (U_FAILURE(status
)) {
340 errln("FAIL: getOffset(5 args) failed.");
342 if (offset
!= -3600000) {
343 errln((UnicodeString
)"FAIL: Invalid time zone raw offset: " + offset
+ " /expected: -3600000");
345 if (dstSavings
!= 0) {
346 errln((UnicodeString
)"FAIL: Invalid DST amount: " + dstSavings
+ " /expected: 0");
350 offset
= rbtz1
->getRawOffset();
351 if (offset
!= -1*HOUR
) {
352 errln((UnicodeString
)"FAIL: Invalid time zone raw offset returned by getRawOffset: "
353 + offset
+ " /expected: -3600000");
357 RuleBasedTimeZone
rbtz0("RBTZ1", ir
->clone());
358 if (rbtz0
== *rbtz1
|| !(rbtz0
!= *rbtz1
)) {
359 errln("FAIL: RuleBasedTimeZone rbtz0 is not equal to rbtz1, but got wrong result");
362 if (rbtz0
!= *rbtz1
|| !(rbtz0
== *rbtz1
)) {
363 errln("FAIL: RuleBasedTimeZone rbtz0 is equal to rbtz1, but got wrong result");
367 const int32_t RAW
= -10*HOUR
;
368 rbtz0
.setRawOffset(RAW
);
369 if (rbtz0
.getRawOffset() != RAW
) {
370 logln("setRawOffset is implemented in RuleBasedTimeZone");
374 if (!rbtz1
->useDaylightTime()) {
375 errln("FAIL: useDaylightTime returned FALSE");
378 // Try to add 3rd final rule
379 dtr
= new DateTimeRule(UCAL_OCTOBER
, 15, 1*HOUR
, DateTimeRule::WALL_TIME
);
380 atzr
= new AnnualTimeZoneRule("3RD_ATZ", -1*HOUR
, 2*HOUR
, dtr
, STARTYEAR
, AnnualTimeZoneRule::MAX_YEAR
);
381 rbtz1
->addTransitionRule(atzr
, status
);
382 if (U_SUCCESS(status
)) {
383 errln("FAIL: 3rd final rule must be rejected");
388 // Try to add an initial rule
389 InitialTimeZoneRule
*ir1
= new InitialTimeZoneRule("Test Initial", 2*HOUR
, 0);
390 rbtz1
->addTransitionRule(ir1
, status
);
391 if (U_SUCCESS(status
)) {
392 errln("FAIL: InitialTimeZoneRule must be rejected");
406 * Test equivalency between OlsonTimeZone and custom RBTZ representing the
407 * equivalent rules in a certain time range
410 TimeZoneRuleTest::TestHistoricalRuleBasedTimeZone(void) {
411 UErrorCode status
= U_ZERO_ERROR
;
413 // Compare to America/New_York with equivalent RBTZ
414 BasicTimeZone
*ny
= (BasicTimeZone
*)TimeZone::createTimeZone("America/New_York");
417 InitialTimeZoneRule
*ir
= new InitialTimeZoneRule("EST", -5*HOUR
, 0);
418 RuleBasedTimeZone
*rbtz
= new RuleBasedTimeZone("EST5EDT", ir
);
421 AnnualTimeZoneRule
*tzr
;
424 dtr
= new DateTimeRule(UCAL_OCTOBER
, -1, UCAL_SUNDAY
,
425 2*HOUR
, DateTimeRule::WALL_TIME
); // Last Sunday in October, at 2AM wall time
426 tzr
= new AnnualTimeZoneRule("EST", -5*HOUR
/*rawOffset*/, 0 /*dstSavings*/, dtr
, 1967, 2006);
427 rbtz
->addTransitionRule(tzr
, status
);
428 if (U_FAILURE(status
)) {
429 errln("FAIL: couldn't add AnnualTimeZoneRule 1.");
432 dtr
= new DateTimeRule(UCAL_NOVEMBER
, 1, UCAL_SUNDAY
,
433 true, 2*HOUR
, DateTimeRule::WALL_TIME
); // SUN>=1 in November, at 2AM wall time
434 tzr
= new AnnualTimeZoneRule("EST", -5*HOUR
, 0, dtr
, 2007, AnnualTimeZoneRule::MAX_YEAR
);
435 rbtz
->addTransitionRule(tzr
, status
);
436 if (U_FAILURE(status
)) {
437 errln("FAIL: couldn't add AnnualTimeZoneRule 2.");
440 // Daylight saving time
441 dtr
= new DateTimeRule(UCAL_APRIL
, -1, UCAL_SUNDAY
,
442 2*HOUR
, DateTimeRule::WALL_TIME
); // Last Sunday in April, at 2AM wall time
443 tzr
= new AnnualTimeZoneRule("EDT", -5*HOUR
, 1*HOUR
, dtr
, 1967, 1973);
444 rbtz
->addTransitionRule(tzr
, status
);
445 if (U_FAILURE(status
)) {
446 errln("FAIL: couldn't add AnnualTimeZoneRule 3.");
449 dtr
= new DateTimeRule(UCAL_JANUARY
, 6,
450 2*HOUR
, DateTimeRule::WALL_TIME
); // January 6, at 2AM wall time
451 tzr
= new AnnualTimeZoneRule("EDT", -5*HOUR
, 1*HOUR
, dtr
, 1974, 1974);
452 rbtz
->addTransitionRule(tzr
, status
);
453 if (U_FAILURE(status
)) {
454 errln("FAIL: couldn't add AnnualTimeZoneRule 4.");
457 dtr
= new DateTimeRule(UCAL_FEBRUARY
, 23,
458 2*HOUR
, DateTimeRule::WALL_TIME
); // February 23, at 2AM wall time
459 tzr
= new AnnualTimeZoneRule("EDT", -5*HOUR
, 1*HOUR
, dtr
, 1975, 1975);
460 rbtz
->addTransitionRule(tzr
, status
);
461 if (U_FAILURE(status
)) {
462 errln("FAIL: couldn't add AnnualTimeZoneRule 5.");
465 dtr
= new DateTimeRule(UCAL_APRIL
, -1, UCAL_SUNDAY
,
466 2*HOUR
, DateTimeRule::WALL_TIME
); // Last Sunday in April, at 2AM wall time
467 tzr
= new AnnualTimeZoneRule("EDT", -5*HOUR
, 1*HOUR
, dtr
, 1976, 1986);
468 rbtz
->addTransitionRule(tzr
, status
);
469 if (U_FAILURE(status
)) {
470 errln("FAIL: couldn't add AnnualTimeZoneRule 6.");
473 dtr
= new DateTimeRule(UCAL_APRIL
, 1, UCAL_SUNDAY
,
474 true, 2*HOUR
, DateTimeRule::WALL_TIME
); // SUN>=1 in April, at 2AM wall time
475 tzr
= new AnnualTimeZoneRule("EDT", -5*HOUR
, 1*HOUR
, dtr
, 1987, 2006);
476 rbtz
->addTransitionRule(tzr
, status
);
477 if (U_FAILURE(status
)) {
478 errln("FAIL: couldn't add AnnualTimeZoneRule 7.");
481 dtr
= new DateTimeRule(UCAL_MARCH
, 8, UCAL_SUNDAY
,
482 true, 2*HOUR
, DateTimeRule::WALL_TIME
); // SUN>=8 in March, at 2AM wall time
483 tzr
= new AnnualTimeZoneRule("EDT", -5*HOUR
, 1*HOUR
, dtr
, 2007, AnnualTimeZoneRule::MAX_YEAR
);
484 rbtz
->addTransitionRule(tzr
, status
);
485 if (U_FAILURE(status
)) {
486 errln("FAIL: couldn't add AnnualTimeZoneRule 7.");
489 rbtz
->complete(status
);
490 if (U_FAILURE(status
)) {
491 errln("FAIL: couldn't complete RBTZ.");
494 // hasEquivalentTransitions
495 UDate jan1_1950
= getUTCMillis(1950, UCAL_JANUARY
, 1);
496 UDate jan1_1967
= getUTCMillis(1971, UCAL_JANUARY
, 1);
497 UDate jan1_2010
= getUTCMillis(2010, UCAL_JANUARY
, 1);
499 if (!ny
->hasEquivalentTransitions(*rbtz
, jan1_1967
, jan1_2010
, TRUE
, status
)) {
500 errln("FAIL: The RBTZ must be equivalent to America/New_York between 1967 and 2010");
502 if (U_FAILURE(status
)) {
503 errln("FAIL: error returned from hasEquivalentTransitions for ny/rbtz 1967-2010");
505 if (ny
->hasEquivalentTransitions(*rbtz
, jan1_1950
, jan1_2010
, TRUE
, status
)) {
506 errln("FAIL: The RBTZ must not be equivalent to America/New_York between 1950 and 2010");
508 if (U_FAILURE(status
)) {
509 errln("FAIL: error returned from hasEquivalentTransitions for ny/rbtz 1950-2010");
512 // Same with above, but calling RBTZ#hasEquivalentTransitions against OlsonTimeZone
513 if (!rbtz
->hasEquivalentTransitions(*ny
, jan1_1967
, jan1_2010
, TRUE
, status
)) {
514 errln("FAIL: The RBTZ must be equivalent to America/New_York between 1967 and 2010");
516 if (U_FAILURE(status
)) {
517 errln("FAIL: error returned from hasEquivalentTransitions for rbtz/ny 1967-2010");
519 if (rbtz
->hasEquivalentTransitions(*ny
, jan1_1950
, jan1_2010
, TRUE
, status
)) {
520 errln("FAIL: The RBTZ must not be equivalent to America/New_York between 1950 and 2010");
522 if (U_FAILURE(status
)) {
523 errln("FAIL: error returned from hasEquivalentTransitions for rbtz/ny 1950-2010");
527 if (ny
->hasSameRules(*rbtz
) || rbtz
->hasSameRules(*ny
)) {
528 errln("FAIL: hasSameRules must return false");
530 RuleBasedTimeZone
*rbtzc
= (RuleBasedTimeZone
*)rbtz
->clone();
531 if (!rbtz
->hasSameRules(*rbtzc
) || !rbtz
->hasEquivalentTransitions(*rbtzc
, jan1_1950
, jan1_2010
, TRUE
, status
)) {
532 errln("FAIL: hasSameRules/hasEquivalentTransitions must return true for cloned RBTZs");
534 if (U_FAILURE(status
)) {
535 errln("FAIL: error returned from hasEquivalentTransitions for rbtz/rbtzc 1950-2010");
539 getUTCMillis(2006, UCAL_MARCH
, 15),
540 getUTCMillis(2006, UCAL_NOVEMBER
, 1),
541 getUTCMillis(2007, UCAL_MARCH
, 15),
542 getUTCMillis(2007, UCAL_NOVEMBER
, 1),
543 getUTCMillis(2008, UCAL_MARCH
, 15),
544 getUTCMillis(2008, UCAL_NOVEMBER
, 1),
547 int32_t offset1
, dst1
;
548 int32_t offset2
, dst2
;
550 for (int i
= 0; times
[i
] != 0; i
++) {
551 // Check getOffset - must return the same results for these time data
552 rbtz
->getOffset(times
[i
], FALSE
, offset1
, dst1
, status
);
553 if (U_FAILURE(status
)) {
554 errln("FAIL: rbtz->getOffset failed");
556 ny
->getOffset(times
[i
], FALSE
, offset2
, dst2
, status
);
557 if (U_FAILURE(status
)) {
558 errln("FAIL: ny->getOffset failed");
560 if (offset1
!= offset2
|| dst1
!= dst2
) {
561 errln("FAIL: Incompatible time zone offset/dstSavings for ny and rbtz");
564 // Check inDaylightTime
565 if (rbtz
->inDaylightTime(times
[i
], status
) != ny
->inDaylightTime(times
[i
], status
)) {
566 errln("FAIL: Incompatible daylight saving time for ny and rbtz");
568 if (U_FAILURE(status
)) {
569 errln("FAIL: inDaylightTime failed");
579 * Check if transitions returned by getNextTransition/getPreviousTransition
580 * are actual time transitions.
583 TimeZoneRuleTest::TestOlsonTransition(void) {
585 const int32_t TESTYEARS
[][2] = {
586 {1895, 1905}, // including int32 minimum second
587 {1965, 1975}, // including the epoch
588 {1995, 2015}, // practical year range
592 UErrorCode status
= U_ZERO_ERROR
;
593 TestZIDEnumeration
tzenum(!quick
);
595 const UnicodeString
*tzid
= tzenum
.snext(status
);
599 if (U_FAILURE(status
)) {
600 errln("FAIL: error returned while enumerating timezone IDs.");
603 BasicTimeZone
*tz
= (BasicTimeZone
*)TimeZone::createTimeZone(*tzid
);
604 for (int32_t i
= 0; TESTYEARS
[i
][0] != 0 || TESTYEARS
[i
][1] != 0; i
++) {
605 UDate lo
= getUTCMillis(TESTYEARS
[i
][0], UCAL_JANUARY
, 1);
606 UDate hi
= getUTCMillis(TESTYEARS
[i
][1], UCAL_JANUARY
, 1);
607 verifyTransitions(*tz
, lo
, hi
);
614 * Check if an OlsonTimeZone and its equivalent RBTZ have the exact same
618 TimeZoneRuleTest::TestRBTZTransition(void) {
619 const int32_t STARTYEARS
[] = {
627 UErrorCode status
= U_ZERO_ERROR
;
628 TestZIDEnumeration
tzenum(!quick
);
630 const UnicodeString
*tzid
= tzenum
.snext(status
);
634 if (U_FAILURE(status
)) {
635 errln("FAIL: error returned while enumerating timezone IDs.");
638 BasicTimeZone
*tz
= (BasicTimeZone
*)TimeZone::createTimeZone(*tzid
);
639 int32_t ruleCount
= tz
->countTransitionRules(status
);
641 const InitialTimeZoneRule
*initial
;
642 const TimeZoneRule
**trsrules
= new const TimeZoneRule
*[ruleCount
];
643 tz
->getTimeZoneRules(initial
, trsrules
, ruleCount
, status
);
644 if (U_FAILURE(status
)) {
645 errln((UnicodeString
)"FAIL: failed to get the TimeZoneRules from time zone " + *tzid
);
647 RuleBasedTimeZone
*rbtz
= new RuleBasedTimeZone(*tzid
, initial
->clone());
648 if (U_FAILURE(status
)) {
649 errln((UnicodeString
)"FAIL: failed to get the transition rule count from time zone " + *tzid
);
651 for (int32_t i
= 0; i
< ruleCount
; i
++) {
652 rbtz
->addTransitionRule(trsrules
[i
]->clone(), status
);
653 if (U_FAILURE(status
)) {
654 errln((UnicodeString
)"FAIL: failed to add a transition rule at index " + i
+ " to the RBTZ for " + *tzid
);
657 rbtz
->complete(status
);
658 if (U_FAILURE(status
)) {
659 errln((UnicodeString
)"FAIL: complete() failed for the RBTZ for " + *tzid
);
662 for (int32_t idx
= 0; STARTYEARS
[idx
] != 0; idx
++) {
663 UDate start
= getUTCMillis(STARTYEARS
[idx
], UCAL_JANUARY
, 1);
664 UDate until
= getUTCMillis(STARTYEARS
[idx
] + 20, UCAL_JANUARY
, 1);
665 // Compare the original OlsonTimeZone with the RBTZ starting the startTime for 20 years
668 compareTransitionsAscending(*tz
, *rbtz
, start
, until
, FALSE
);
669 // Ascending/inclusive
670 compareTransitionsAscending(*tz
, *rbtz
, start
+ 1, until
, TRUE
);
672 compareTransitionsDescending(*tz
, *rbtz
, start
, until
, FALSE
);
673 // Descending/inclusive
674 compareTransitionsDescending(*tz
, *rbtz
, start
+ 1, until
, TRUE
);
683 TimeZoneRuleTest::TestHasEquivalentTransitions(void) {
684 // America/New_York and America/Indiana/Indianapolis are equivalent
686 UErrorCode status
= U_ZERO_ERROR
;
687 BasicTimeZone
*newyork
= (BasicTimeZone
*)TimeZone::createTimeZone("America/New_York");
688 BasicTimeZone
*indianapolis
= (BasicTimeZone
*)TimeZone::createTimeZone("America/Indiana/Indianapolis");
689 BasicTimeZone
*gmt_5
= (BasicTimeZone
*)TimeZone::createTimeZone("Etc/GMT+5");
691 UDate jan1_1971
= getUTCMillis(1971, UCAL_JANUARY
, 1);
692 UDate jan1_2005
= getUTCMillis(2005, UCAL_JANUARY
, 1);
693 UDate jan1_2006
= getUTCMillis(2006, UCAL_JANUARY
, 1);
694 UDate jan1_2007
= getUTCMillis(2007, UCAL_JANUARY
, 1);
695 UDate jan1_2011
= getUTCMillis(2010, UCAL_JANUARY
, 1);
697 if (newyork
->hasEquivalentTransitions(*indianapolis
, jan1_2005
, jan1_2011
, TRUE
, status
)) {
698 errln("FAIL: New_York is not equivalent to Indianapolis between 2005 and 2010");
700 if (U_FAILURE(status
)) {
701 errln("FAIL: error status is returned from hasEquivalentTransition");
703 if (!newyork
->hasEquivalentTransitions(*indianapolis
, jan1_2006
, jan1_2011
, TRUE
, status
)) {
704 errln("FAIL: New_York is equivalent to Indianapolis between 2006 and 2010");
706 if (U_FAILURE(status
)) {
707 errln("FAIL: error status is returned from hasEquivalentTransition");
710 if (!indianapolis
->hasEquivalentTransitions(*gmt_5
, jan1_1971
, jan1_2006
, TRUE
, status
)) {
711 errln("FAIL: Indianapolis is equivalent to GMT+5 between 1971 and 2005");
713 if (U_FAILURE(status
)) {
714 errln("FAIL: error status is returned from hasEquivalentTransition");
716 if (indianapolis
->hasEquivalentTransitions(*gmt_5
, jan1_1971
, jan1_2007
, TRUE
, status
)) {
717 errln("FAIL: Indianapolis is not equivalent to GMT+5 between 1971 and 2006");
719 if (U_FAILURE(status
)) {
720 errln("FAIL: error status is returned from hasEquivalentTransition");
724 BasicTimeZone
*newyork2
= (BasicTimeZone
*)newyork
->clone();
725 if (!newyork
->hasEquivalentTransitions(*newyork2
, jan1_1971
, jan1_2011
, FALSE
, status
)) {
726 errln("FAIL: Cloned TimeZone must have the same transitions");
728 if (U_FAILURE(status
)) {
729 errln("FAIL: error status is returned from hasEquivalentTransition for newyork/newyork2");
731 if (!newyork
->hasEquivalentTransitions(*newyork2
, jan1_1971
, jan1_2011
, TRUE
, status
)) {
732 errln("FAIL: Cloned TimeZone must have the same transitions");
734 if (U_FAILURE(status
)) {
735 errln("FAIL: error status is returned from hasEquivalentTransition for newyork/newyork2");
738 // America/New_York and America/Los_Angeles has same DST start rules, but
739 // raw offsets are different
740 BasicTimeZone
*losangeles
= (BasicTimeZone
*)TimeZone::createTimeZone("America/Los_Angeles");
741 if (newyork
->hasEquivalentTransitions(*losangeles
, jan1_2006
, jan1_2011
, TRUE
, status
)) {
742 errln("FAIL: New_York is not equivalent to Los Angeles, but returned true");
744 if (U_FAILURE(status
)) {
745 errln("FAIL: error status is returned from hasEquivalentTransition for newyork/losangeles");
756 * Write out time zone rules of OlsonTimeZone into VTIMEZONE format, create a new
757 * VTimeZone from the VTIMEZONE data, then compare transitions
760 TimeZoneRuleTest::TestVTimeZoneRoundTrip(void) {
761 UDate startTime
= getUTCMillis(1850, UCAL_JANUARY
, 1);
762 UDate endTime
= getUTCMillis(2050, UCAL_JANUARY
, 1);
764 UErrorCode status
= U_ZERO_ERROR
;
765 TestZIDEnumeration
tzenum(!quick
);
767 const UnicodeString
*tzid
= tzenum
.snext(status
);
771 if (U_FAILURE(status
)) {
772 errln("FAIL: error returned while enumerating timezone IDs.");
775 BasicTimeZone
*tz
= (BasicTimeZone
*)TimeZone::createTimeZone(*tzid
);
776 VTimeZone
*vtz_org
= VTimeZone::createVTimeZoneByID(*tzid
);
777 vtz_org
->setTZURL("http://source.icu-project.org/timezone");
778 vtz_org
->setLastModified(Calendar::getNow());
779 VTimeZone
*vtz_new
= NULL
;
780 UnicodeString vtzdata
;
781 // Write out VTIMEZONE data
782 vtz_org
->write(vtzdata
, status
);
783 if (U_FAILURE(status
)) {
784 errln((UnicodeString
)"FAIL: error returned while writing time zone rules for " +
785 *tzid
+ " into VTIMEZONE format.");
787 // Read VTIMEZONE data
788 vtz_new
= VTimeZone::createVTimeZone(vtzdata
, status
);
789 if (U_FAILURE(status
)) {
790 errln((UnicodeString
)"FAIL: error returned while reading VTIMEZONE data for " + *tzid
);
792 // Write out VTIMEZONE one more time
793 UnicodeString vtzdata1
;
794 vtz_new
->write(vtzdata1
, status
);
795 if (U_FAILURE(status
)) {
796 errln((UnicodeString
)"FAIL: error returned while writing time zone rules for " +
797 *tzid
+ "(vtz_new) into VTIMEZONE format.");
799 // Make sure VTIMEZONE data is exactly same with the first one
800 if (vtzdata
!= vtzdata1
) {
801 errln((UnicodeString
)"FAIL: different VTIMEZONE data after round trip for " + *tzid
);
804 // Check equivalency after the first transition.
805 // The DST information before the first transition might be lost
806 // because there is no good way to represent the initial time with
808 int32_t raw1
, raw2
, dst1
, dst2
;
809 tz
->getOffset(startTime
, FALSE
, raw1
, dst1
, status
);
810 vtz_new
->getOffset(startTime
, FALSE
, raw2
, dst2
, status
);
811 if (U_FAILURE(status
)) {
812 errln("FAIL: error status is returned from getOffset");
814 if (raw1
+ dst1
!= raw2
+ dst2
) {
815 errln("FAIL: VTimeZone for " + *tzid
+
816 " is not equivalent to its OlsonTimeZone corresponding at "
817 + dateToString(startTime
));
819 TimeZoneTransition trans
;
820 UBool avail
= tz
->getNextTransition(startTime
, FALSE
, trans
);
822 if (!vtz_new
->hasEquivalentTransitions(*tz
, trans
.getTime(),
823 endTime
, TRUE
, status
)) {
824 errln("FAIL: VTimeZone for " + *tzid
+
825 " is not equivalent to its OlsonTimeZone corresponding.");
827 if (U_FAILURE(status
)) {
828 errln("FAIL: error status is returned from hasEquivalentTransition");
833 if (vtz_new
!= NULL
) {
844 * Write out time zone rules of OlsonTimeZone after a cutover date into VTIMEZONE format,
845 * create a new VTimeZone from the VTIMEZONE data, then compare transitions
848 TimeZoneRuleTest::TestVTimeZoneRoundTripPartial(void) {
849 const int32_t STARTYEARS
[] = {
855 UDate endTime
= getUTCMillis(2050, UCAL_JANUARY
, 1);
857 UErrorCode status
= U_ZERO_ERROR
;
858 TestZIDEnumeration
tzenum(!quick
);
860 const UnicodeString
*tzid
= tzenum
.snext(status
);
864 if (U_FAILURE(status
)) {
865 errln("FAIL: error returned while enumerating timezone IDs.");
868 BasicTimeZone
*tz
= (BasicTimeZone
*)TimeZone::createTimeZone(*tzid
);
869 VTimeZone
*vtz_org
= VTimeZone::createVTimeZoneByID(*tzid
);
870 VTimeZone
*vtz_new
= NULL
;
871 UnicodeString vtzdata
;
873 for (int32_t i
= 0; STARTYEARS
[i
] != 0; i
++) {
874 // Write out VTIMEZONE
875 UDate startTime
= getUTCMillis(STARTYEARS
[i
], UCAL_JANUARY
, 1);
876 vtz_org
->write(startTime
, vtzdata
, status
);
877 if (U_FAILURE(status
)) {
878 errln((UnicodeString
)"FAIL: error returned while writing time zone rules for " +
879 *tzid
+ " into VTIMEZONE format since " + dateToString(startTime
));
881 // Read VTIMEZONE data
882 vtz_new
= VTimeZone::createVTimeZone(vtzdata
, status
);
883 if (U_FAILURE(status
)) {
884 errln((UnicodeString
)"FAIL: error returned while reading VTIMEZONE data for " + *tzid
885 + " since " + dateToString(startTime
));
887 // Check equivalency after the first transition.
888 // The DST information before the first transition might be lost
889 // because there is no good way to represent the initial time with
891 int32_t raw1
, raw2
, dst1
, dst2
;
892 tz
->getOffset(startTime
, FALSE
, raw1
, dst1
, status
);
893 vtz_new
->getOffset(startTime
, FALSE
, raw2
, dst2
, status
);
894 if (U_FAILURE(status
)) {
895 errln("FAIL: error status is returned from getOffset");
897 if (raw1
+ dst1
!= raw2
+ dst2
) {
898 errln("FAIL: VTimeZone for " + *tzid
+
899 " is not equivalent to its OlsonTimeZone corresponding at "
900 + dateToString(startTime
));
902 TimeZoneTransition trans
;
903 UBool avail
= tz
->getNextTransition(startTime
, FALSE
, trans
);
905 if (!vtz_new
->hasEquivalentTransitions(*tz
, trans
.getTime(),
906 endTime
, TRUE
, status
)) {
907 errln("FAIL: VTimeZone for " + *tzid
+
908 " is not equivalent to its OlsonTimeZone corresponding.");
910 if (U_FAILURE(status
)) {
911 errln("FAIL: error status is returned from hasEquivalentTransition");
917 if (vtz_new
!= NULL
) {
928 * Write out simple time zone rules from an OlsonTimeZone at various time into VTIMEZONE
929 * format and create a new VTimeZone from the VTIMEZONE data, then make sure the raw offset
930 * and DST savings are same in these two time zones.
933 TimeZoneRuleTest::TestVTimeZoneSimpleWrite(void) {
934 const int32_t TESTDATES
[][3] = {
935 {2006, UCAL_JANUARY
, 1},
936 {2006, UCAL_MARCH
, 15},
937 {2006, UCAL_MARCH
, 31},
938 {2006, UCAL_OCTOBER
, 25},
939 {2006, UCAL_NOVEMBER
, 1},
940 {2006, UCAL_NOVEMBER
, 5},
941 {2007, UCAL_JANUARY
, 1},
945 UErrorCode status
= U_ZERO_ERROR
;
946 TestZIDEnumeration
tzenum(!quick
);
948 const UnicodeString
*tzid
= tzenum
.snext(status
);
952 if (U_FAILURE(status
)) {
953 errln("FAIL: error returned while enumerating timezone IDs.");
956 VTimeZone
*vtz_org
= VTimeZone::createVTimeZoneByID(*tzid
);
957 VTimeZone
*vtz_new
= NULL
;
958 UnicodeString vtzdata
;
960 for (int32_t i
= 0; TESTDATES
[i
][0] != 0; i
++) {
961 // Write out VTIMEZONE
962 UDate time
= getUTCMillis(TESTDATES
[i
][0], TESTDATES
[i
][1], TESTDATES
[i
][2]);
963 vtz_org
->writeSimple(time
, vtzdata
, status
);
964 if (U_FAILURE(status
)) {
965 errln((UnicodeString
)"FAIL: error returned while writing simple time zone rules for " +
966 *tzid
+ " into VTIMEZONE format at " + dateToString(time
));
968 // Read VTIMEZONE data
969 vtz_new
= VTimeZone::createVTimeZone(vtzdata
, status
);
970 if (U_FAILURE(status
)) {
971 errln((UnicodeString
)"FAIL: error returned while reading simple VTIMEZONE data for " + *tzid
972 + " at " + dateToString(time
));
977 vtz_org
->getOffset(time
, FALSE
, raw0
, dst0
, status
);
978 vtz_new
->getOffset(time
, FALSE
, raw1
, dst1
, status
);
979 if (U_SUCCESS(status
)) {
980 if (raw0
!= raw1
|| dst0
!= dst1
) {
981 errln("FAIL: VTimeZone writeSimple for " + *tzid
+ " at "
982 + dateToString(time
) + " failed to the round trip.");
985 errln("FAIL: getOffset returns error status");
989 if (vtz_new
!= NULL
) {
999 * Write out time zone rules of OlsonTimeZone into VTIMEZONE format with RFC2445 header TZURL and
1000 * LAST-MODIFIED, create a new VTimeZone from the VTIMEZONE data to see if the headers are preserved.
1003 TimeZoneRuleTest::TestVTimeZoneHeaderProps(void) {
1004 const UnicodeString
TESTURL1("http://source.icu-project.org");
1005 const UnicodeString
TESTURL2("http://www.ibm.com");
1007 UErrorCode status
= U_ZERO_ERROR
;
1008 UnicodeString tzurl
;
1010 UDate lastmod
= getUTCMillis(2007, UCAL_JUNE
, 1);
1011 VTimeZone
*vtz
= VTimeZone::createVTimeZoneByID("America/Chicago");
1012 vtz
->setTZURL(TESTURL1
);
1013 vtz
->setLastModified(lastmod
);
1015 // Roundtrip conversion
1016 UnicodeString vtzdata
;
1017 vtz
->write(vtzdata
, status
);
1018 VTimeZone
*newvtz1
= NULL
;
1019 if (U_FAILURE(status
)) {
1020 errln("FAIL: error returned while writing VTIMEZONE data 1");
1024 newvtz1
= VTimeZone::createVTimeZone(vtzdata
, status
);
1025 if (U_FAILURE(status
)) {
1026 errln("FAIL: error returned while loading VTIMEZONE data 1");
1028 // Check if TZURL and LAST-MODIFIED properties are preserved
1029 newvtz1
->getTZURL(tzurl
);
1030 if (tzurl
!= TESTURL1
) {
1031 errln("FAIL: TZURL 1 was not preserved");
1033 vtz
->getLastModified(lmod
);
1034 if (lastmod
!= lmod
) {
1035 errln("FAIL: LAST-MODIFIED was not preserved");
1039 if (U_SUCCESS(status
)) {
1040 // Set different tzurl
1041 newvtz1
->setTZURL(TESTURL2
);
1043 // Second roundtrip, with a cutover
1044 newvtz1
->write(vtzdata
, status
);
1045 if (U_FAILURE(status
)) {
1046 errln("FAIL: error returned while writing VTIMEZONE data 2");
1048 VTimeZone
*newvtz2
= VTimeZone::createVTimeZone(vtzdata
, status
);
1049 if (U_FAILURE(status
)) {
1050 errln("FAIL: error returned while loading VTIMEZONE data 2");
1052 // Check if TZURL and LAST-MODIFIED properties are preserved
1053 newvtz2
->getTZURL(tzurl
);
1054 if (tzurl
!= TESTURL2
) {
1055 errln("FAIL: TZURL was not preserved in the second roundtrip");
1057 vtz
->getLastModified(lmod
);
1058 if (lastmod
!= lmod
) {
1059 errln("FAIL: LAST-MODIFIED was not preserved in the second roundtrip");
1070 * Extract simple rules from an OlsonTimeZone and make sure the rule format matches
1071 * the expected format.
1074 TimeZoneRuleTest::TestGetSimpleRules(void) {
1075 UDate testTimes
[] = {
1076 getUTCMillis(1970, UCAL_JANUARY
, 1),
1077 getUTCMillis(2000, UCAL_MARCH
, 31),
1078 getUTCMillis(2005, UCAL_JULY
, 1),
1079 getUTCMillis(2010, UCAL_NOVEMBER
, 1),
1081 int32_t numTimes
= sizeof(testTimes
)/sizeof(UDate
);
1082 UErrorCode status
= U_ZERO_ERROR
;
1083 TestZIDEnumeration
tzenum(!quick
);
1084 InitialTimeZoneRule
*initial
;
1085 AnnualTimeZoneRule
*std
, *dst
;
1086 for (int32_t i
= 0; i
< numTimes
; i
++) {
1088 const UnicodeString
*tzid
= tzenum
.snext(status
);
1092 if (U_FAILURE(status
)) {
1093 errln("FAIL: error returned while enumerating timezone IDs.");
1096 BasicTimeZone
*tz
= (BasicTimeZone
*)TimeZone::createTimeZone(*tzid
);
1099 tz
->getSimpleRulesNear(testTimes
[i
], initial
, std
, dst
, status
);
1100 if (U_FAILURE(status
)) {
1101 errln("FAIL: getSimpleRules failed.");
1104 if (initial
== NULL
) {
1105 errln("FAIL: initial rule must not be NULL");
1107 } else if (!(std
== NULL
&& dst
== NULL
|| std
!= NULL
&& dst
!= NULL
)) {
1108 errln("FAIL: invalid std/dst pair.");
1112 const DateTimeRule
*dtr
= std
->getRule();
1113 if (dtr
->getDateRuleType() != DateTimeRule::DOW
) {
1114 errln("FAIL: simple std rull must use DateTimeRule::DOW as date rule.");
1117 if (dtr
->getTimeRuleType() != DateTimeRule::WALL_TIME
) {
1118 errln("FAIL: simple std rull must use DateTimeRule::WALL_TIME as time rule.");
1121 dtr
= dst
->getRule();
1122 if (dtr
->getDateRuleType() != DateTimeRule::DOW
) {
1123 errln("FAIL: simple dst rull must use DateTimeRule::DOW as date rule.");
1126 if (dtr
->getTimeRuleType() != DateTimeRule::WALL_TIME
) {
1127 errln("FAIL: simple dst rull must use DateTimeRule::WALL_TIME as time rule.");
1131 // Create an RBTZ from the rules and compare the offsets at the date
1132 RuleBasedTimeZone
*rbtz
= new RuleBasedTimeZone(*tzid
, initial
);
1134 rbtz
->addTransitionRule(std
, status
);
1135 if (U_FAILURE(status
)) {
1136 errln("FAIL: couldn't add std rule.");
1138 rbtz
->addTransitionRule(dst
, status
);
1139 if (U_FAILURE(status
)) {
1140 errln("FAIL: couldn't add dst rule.");
1143 rbtz
->complete(status
);
1144 if (U_FAILURE(status
)) {
1145 errln("FAIL: couldn't complete rbtz for " + *tzid
);
1148 int32_t raw0
, dst0
, raw1
, dst1
;
1149 tz
->getOffset(testTimes
[i
], FALSE
, raw0
, dst0
, status
);
1150 if (U_FAILURE(status
)) {
1151 errln("FAIL: couldn't get offsets from tz for " + *tzid
);
1153 rbtz
->getOffset(testTimes
[i
], FALSE
, raw1
, dst1
, status
);
1154 if (U_FAILURE(status
)) {
1155 errln("FAIL: couldn't get offsets from rbtz for " + *tzid
);
1157 if (raw0
!= raw1
|| dst0
!= dst1
) {
1158 errln("FAIL: rbtz created by simple rule does not match the original tz for tzid " + *tzid
);
1167 * API coverage tests for TimeZoneRule
1170 TimeZoneRuleTest::TestTimeZoneRuleCoverage(void) {
1171 UDate time1
= getUTCMillis(2005, UCAL_JULY
, 4);
1172 UDate time2
= getUTCMillis(2015, UCAL_JULY
, 4);
1173 UDate time3
= getUTCMillis(1950, UCAL_JULY
, 4);
1175 DateTimeRule
*dtr1
= new DateTimeRule(UCAL_FEBRUARY
, 29, UCAL_SUNDAY
, FALSE
,
1176 3*HOUR
, DateTimeRule::WALL_TIME
); // Last Sunday on or before Feb 29, at 3 AM, wall time
1177 DateTimeRule
*dtr2
= new DateTimeRule(UCAL_MARCH
, 11, 2*HOUR
,
1178 DateTimeRule::STANDARD_TIME
); // Mar 11, at 2 AM, standard time
1179 DateTimeRule
*dtr3
= new DateTimeRule(UCAL_OCTOBER
, -1, UCAL_SATURDAY
,
1180 6*HOUR
, DateTimeRule::UTC_TIME
); //Last Saturday in Oct, at 6 AM, UTC
1181 DateTimeRule
*dtr4
= new DateTimeRule(UCAL_MARCH
, 8, UCAL_SUNDAY
, TRUE
,
1182 2*HOUR
, DateTimeRule::WALL_TIME
); // First Sunday on or after Mar 8, at 2 AM, wall time
1184 AnnualTimeZoneRule
*a1
= new AnnualTimeZoneRule("a1", -3*HOUR
, 1*HOUR
, *dtr1
,
1185 2000, AnnualTimeZoneRule::MAX_YEAR
);
1186 AnnualTimeZoneRule
*a2
= new AnnualTimeZoneRule("a2", -3*HOUR
, 1*HOUR
, *dtr1
,
1187 2000, AnnualTimeZoneRule::MAX_YEAR
);
1188 AnnualTimeZoneRule
*a3
= new AnnualTimeZoneRule("a3", -3*HOUR
, 1*HOUR
, *dtr1
,
1191 InitialTimeZoneRule
*i1
= new InitialTimeZoneRule("i1", -3*HOUR
, 0);
1192 InitialTimeZoneRule
*i2
= new InitialTimeZoneRule("i2", -3*HOUR
, 0);
1193 InitialTimeZoneRule
*i3
= new InitialTimeZoneRule("i3", -3*HOUR
, 1*HOUR
);
1195 UDate trtimes1
[] = {0.0};
1196 UDate trtimes2
[] = {0.0, 10000000.0};
1198 TimeArrayTimeZoneRule
*t1
= new TimeArrayTimeZoneRule("t1", -3*HOUR
, 0, trtimes1
, 1, DateTimeRule::UTC_TIME
);
1199 TimeArrayTimeZoneRule
*t2
= new TimeArrayTimeZoneRule("t2", -3*HOUR
, 0, trtimes1
, 1, DateTimeRule::UTC_TIME
);
1200 TimeArrayTimeZoneRule
*t3
= new TimeArrayTimeZoneRule("t3", -3*HOUR
, 0, trtimes2
, 2, DateTimeRule::UTC_TIME
);
1201 TimeArrayTimeZoneRule
*t4
= new TimeArrayTimeZoneRule("t4", -3*HOUR
, 0, trtimes1
, 1, DateTimeRule::STANDARD_TIME
);
1202 TimeArrayTimeZoneRule
*t5
= new TimeArrayTimeZoneRule("t5", -4*HOUR
, 1*HOUR
, trtimes1
, 1, DateTimeRule::WALL_TIME
);
1204 // DateTimeRule::operator=/clone
1205 DateTimeRule
dtr0(UCAL_MAY
, 31, 2*HOUR
, DateTimeRule::WALL_TIME
);
1206 if (dtr0
== *dtr1
|| !(dtr0
!= *dtr1
)) {
1207 errln("FAIL: DateTimeRule dtr0 is not equal to dtr1, but got wrong result");
1210 if (dtr0
!= *dtr1
|| !(dtr0
== *dtr1
)) {
1211 errln("FAIL: DateTimeRule dtr0 is equal to dtr1, but got wrong result");
1213 DateTimeRule
*dtr0c
= dtr0
.clone();
1214 if (*dtr0c
!= *dtr1
|| !(*dtr0c
== *dtr1
)) {
1215 errln("FAIL: DateTimeRule dtr0c is equal to dtr1, but got wrong result");
1219 // AnnualTimeZonerule::operator=/clone
1220 AnnualTimeZoneRule
a0("a0", 5*HOUR
, 1*HOUR
, *dtr1
, 1990, AnnualTimeZoneRule::MAX_YEAR
);
1221 if (a0
== *a1
|| !(a0
!= *a1
)) {
1222 errln("FAIL: AnnualTimeZoneRule a0 is not equal to a1, but got wrong result");
1225 if (a0
!= *a1
|| !(a0
== *a1
)) {
1226 errln("FAIL: AnnualTimeZoneRule a0 is equal to a1, but got wrong result");
1228 AnnualTimeZoneRule
*a0c
= a0
.clone();
1229 if (*a0c
!= *a1
|| !(*a0c
== *a1
)) {
1230 errln("FAIL: AnnualTimeZoneRule a0c is equal to a1, but got wrong result");
1234 // AnnualTimeZoneRule::getRule
1235 if (*(a1
->getRule()) != *(a2
->getRule())) {
1236 errln("FAIL: The same DateTimeRule must be returned from AnnualTimeZoneRule a1 and a2");
1239 // AnnualTimeZoneRule::getStartYear
1240 int32_t startYear
= a1
->getStartYear();
1241 if (startYear
!= 2000) {
1242 errln((UnicodeString
)"FAIL: The start year of AnnualTimeZoneRule a1 must be 2000 - returned: " + startYear
);
1245 // AnnualTimeZoneRule::getEndYear
1246 int32_t endYear
= a1
->getEndYear();
1247 if (endYear
!= AnnualTimeZoneRule::MAX_YEAR
) {
1248 errln((UnicodeString
)"FAIL: The start year of AnnualTimeZoneRule a1 must be MAX_YEAR - returned: " + endYear
);
1250 endYear
= a3
->getEndYear();
1251 if (endYear
!= 2010) {
1252 errln((UnicodeString
)"FAIL: The start year of AnnualTimeZoneRule a3 must be 2010 - returned: " + endYear
);
1255 // AnnualTimeZone::getStartInYear
1258 b1
= a1
->getStartInYear(2005, -3*HOUR
, 0, d1
);
1259 b2
= a3
->getStartInYear(2005, -3*HOUR
, 0, d2
);
1260 if (!b1
|| !b2
|| d1
!= d2
) {
1261 errln("FAIL: AnnualTimeZoneRule::getStartInYear did not work as expected");
1263 b2
= a3
->getStartInYear(2015, -3*HOUR
, 0, d2
);
1265 errln("FAIL: AnnualTimeZoneRule::getStartInYear returned TRUE for 2015 which is out of rule range");
1268 // AnnualTimeZone::getFirstStart
1269 b1
= a1
->getFirstStart(-3*HOUR
, 0, d1
);
1270 b2
= a1
->getFirstStart(-4*HOUR
, 1*HOUR
, d2
);
1271 if (!b1
|| !b2
|| d1
!= d2
) {
1272 errln("FAIL: The same start time should be returned by getFirstStart");
1275 // AnnualTimeZone::getFinalStart
1276 b1
= a1
->getFinalStart(-3*HOUR
, 0, d1
);
1278 errln("FAIL: getFinalStart returned TRUE for a1");
1280 b1
= a1
->getStartInYear(2010, -3*HOUR
, 0, d1
);
1281 b2
= a3
->getFinalStart(-3*HOUR
, 0, d2
);
1282 if (!b1
|| !b2
|| d1
!= d2
) {
1283 errln("FAIL: Bad date is returned by getFinalStart");
1286 // AnnualTimeZone::getNextStart / getPreviousStart
1287 b1
= a1
->getNextStart(time1
, -3*HOUR
, 0, FALSE
, d1
);
1289 errln("FAIL: getNextStart returned FALSE for ai");
1291 b2
= a1
->getPreviousStart(d1
, -3*HOUR
, 0, TRUE
, d2
);
1292 if (!b2
|| d1
!= d2
) {
1293 errln("FAIL: Bad Date is returned by getPreviousStart");
1296 b1
= a3
->getNextStart(time2
, -3*HOUR
, 0, FALSE
, d1
);
1298 errln("FAIL: getNextStart must return FALSE when no start time is available after the base time");
1300 b1
= a3
->getFinalStart(-3*HOUR
, 0, d1
);
1301 b2
= a3
->getPreviousStart(time2
, -3*HOUR
, 0, FALSE
, d2
);
1302 if (!b1
|| !b2
|| d1
!= d2
) {
1303 errln("FAIL: getPreviousStart does not match with getFinalStart after the end year");
1306 // AnnualTimeZone::isEquavalentTo
1307 if (!a1
->isEquivalentTo(*a2
)) {
1308 errln("FAIL: AnnualTimeZoneRule a1 is equivalent to a2, but returned FALSE");
1310 if (a1
->isEquivalentTo(*a3
)) {
1311 errln("FAIL: AnnualTimeZoneRule a1 is not equivalent to a3, but returned TRUE");
1313 if (!a1
->isEquivalentTo(*a1
)) {
1314 errln("FAIL: AnnualTimeZoneRule a1 is equivalent to itself, but returned FALSE");
1316 if (a1
->isEquivalentTo(*t1
)) {
1317 errln("FAIL: AnnualTimeZoneRule is not equivalent to TimeArrayTimeZoneRule, but returned TRUE");
1320 // InitialTimezoneRule::operator=/clone
1321 InitialTimeZoneRule
i0("i0", 10*HOUR
, 0);
1322 if (i0
== *i1
|| !(i0
!= *i1
)) {
1323 errln("FAIL: InitialTimeZoneRule i0 is not equal to i1, but got wrong result");
1326 if (i0
!= *i1
|| !(i0
== *i1
)) {
1327 errln("FAIL: InitialTimeZoneRule i0 is equal to i1, but got wrong result");
1329 InitialTimeZoneRule
*i0c
= i0
.clone();
1330 if (*i0c
!= *i1
|| !(*i0c
== *i1
)) {
1331 errln("FAIL: InitialTimeZoneRule i0c is equal to i1, but got wrong result");
1335 // InitialTimeZoneRule::isEquivalentRule
1336 if (!i1
->isEquivalentTo(*i2
)) {
1337 errln("FAIL: InitialTimeZoneRule i1 is equivalent to i2, but returned FALSE");
1339 if (i1
->isEquivalentTo(*i3
)) {
1340 errln("FAIL: InitialTimeZoneRule i1 is not equivalent to i3, but returned TRUE");
1342 if (i1
->isEquivalentTo(*a1
)) {
1343 errln("FAIL: An InitialTimeZoneRule is not equivalent to an AnnualTimeZoneRule, but returned TRUE");
1346 // InitialTimeZoneRule::getFirstStart/getFinalStart/getNextStart/getPreviousStart
1347 b1
= i1
->getFirstStart(0, 0, d1
);
1349 errln("FAIL: InitialTimeZone::getFirstStart returned TRUE");
1351 b1
= i1
->getFinalStart(0, 0, d1
);
1353 errln("FAIL: InitialTimeZone::getFinalStart returned TRUE");
1355 b1
= i1
->getNextStart(time1
, 0, 0, FALSE
, d1
);
1357 errln("FAIL: InitialTimeZone::getNextStart returned TRUE");
1359 b1
= i1
->getPreviousStart(time1
, 0, 0, FALSE
, d1
);
1361 errln("FAIL: InitialTimeZone::getPreviousStart returned TRUE");
1364 // TimeArrayTimeZoneRule::operator=/clone
1365 TimeArrayTimeZoneRule
t0("t0", 4*HOUR
, 0, trtimes1
, 1, DateTimeRule::UTC_TIME
);
1366 if (t0
== *t1
|| !(t0
!= *t1
)) {
1367 errln("FAIL: TimeArrayTimeZoneRule t0 is not equal to t1, but got wrong result");
1370 if (t0
!= *t1
|| !(t0
== *t1
)) {
1371 errln("FAIL: TimeArrayTimeZoneRule t0 is equal to t1, but got wrong result");
1373 TimeArrayTimeZoneRule
*t0c
= t0
.clone();
1374 if (*t0c
!= *t1
|| !(*t0c
== *t1
)) {
1375 errln("FAIL: TimeArrayTimeZoneRule t0c is equal to t1, but got wrong result");
1379 // TimeArrayTimeZoneRule::countStartTimes
1380 if (t1
->countStartTimes() != 1) {
1381 errln("FAIL: Bad start time count is returned by TimeArrayTimeZoneRule::countStartTimes");
1384 // TimeArrayTimeZoneRule::getStartTimeAt
1385 b1
= t1
->getStartTimeAt(-1, d1
);
1387 errln("FAIL: TimeArrayTimeZoneRule::getStartTimeAt returned TRUE for index -1");
1389 b1
= t1
->getStartTimeAt(0, d1
);
1390 if (!b1
|| d1
!= trtimes1
[0]) {
1391 errln("FAIL: TimeArrayTimeZoneRule::getStartTimeAt returned incorrect result for index 0");
1393 b1
= t1
->getStartTimeAt(1, d1
);
1395 errln("FAIL: TimeArrayTimeZoneRule::getStartTimeAt returned TRUE for index 1");
1398 // TimeArrayTimeZoneRule::getTimeType
1399 if (t1
->getTimeType() != DateTimeRule::UTC_TIME
) {
1400 errln("FAIL: TimeArrayTimeZoneRule t1 uses UTC_TIME, but different type is returned");
1402 if (t4
->getTimeType() != DateTimeRule::STANDARD_TIME
) {
1403 errln("FAIL: TimeArrayTimeZoneRule t4 uses STANDARD_TIME, but different type is returned");
1405 if (t5
->getTimeType() != DateTimeRule::WALL_TIME
) {
1406 errln("FAIL: TimeArrayTimeZoneRule t5 uses WALL_TIME, but different type is returned");
1409 // TimeArrayTimeZoneRule::getFirstStart/getFinalStart
1410 b1
= t1
->getFirstStart(0, 0, d1
);
1411 if (!b1
|| d1
!= trtimes1
[0]) {
1412 errln("FAIL: Bad first start time returned from TimeArrayTimeZoneRule t1");
1414 b1
= t1
->getFinalStart(0, 0, d1
);
1415 if (!b1
|| d1
!= trtimes1
[0]) {
1416 errln("FAIL: Bad final start time returned from TimeArrayTimeZoneRule t1");
1418 b1
= t4
->getFirstStart(-4*HOUR
, 1*HOUR
, d1
);
1419 if (!b1
|| d1
!= (trtimes1
[0] + 4*HOUR
)) {
1420 errln("FAIL: Bad first start time returned from TimeArrayTimeZoneRule t4");
1422 b1
= t5
->getFirstStart(-4*HOUR
, 1*HOUR
, d1
);
1423 if (!b1
|| d1
!= (trtimes1
[0] + 3*HOUR
)) {
1424 errln("FAIL: Bad first start time returned from TimeArrayTimeZoneRule t5");
1427 // TimeArrayTimeZoneRule::getNextStart/getPreviousStart
1428 b1
= t3
->getNextStart(time1
, -3*HOUR
, 1*HOUR
, FALSE
, d1
);
1430 errln("FAIL: getNextStart returned TRUE after the final transition for t3");
1432 b1
= t3
->getPreviousStart(time1
, -3*HOUR
, 1*HOUR
, FALSE
, d1
);
1433 if (!b1
|| d1
!= trtimes2
[1]) {
1434 errln("FAIL: Bad start time returned by getPreviousStart for t3");
1436 b2
= t3
->getPreviousStart(d1
, -3*HOUR
, 1*HOUR
, FALSE
, d2
);
1437 if (!b2
|| d2
!= trtimes2
[0]) {
1438 errln("FAIL: Bad start time returned by getPreviousStart for t3");
1441 b1
= t3
->getPreviousStart(time3
, -3*HOUR
, 1*HOUR
, FALSE
, d1
); //time3 - year 1950, no result expected
1443 errln("FAIL: getPreviousStart returned TRUE before the first transition for t3");
1446 // TimeArrayTimeZoneRule::isEquivalentTo
1447 if (!t1
->isEquivalentTo(*t2
)) {
1448 errln("FAIL: TimeArrayTimeZoneRule t1 is equivalent to t2, but returned FALSE");
1450 if (t1
->isEquivalentTo(*t3
)) {
1451 errln("FAIL: TimeArrayTimeZoneRule t1 is not equivalent to t3, but returned TRUE");
1453 if (t1
->isEquivalentTo(*t4
)) {
1454 errln("FAIL: TimeArrayTimeZoneRule t1 is not equivalent to t4, but returned TRUE");
1456 if (t1
->isEquivalentTo(*a1
)) {
1457 errln("FAIL: TimeArrayTimeZoneRule is not equivalent to AnnualTimeZoneRule, but returned TRUE");
1478 * API coverage test for BasicTimeZone APIs in SimpleTimeZone
1481 TimeZoneRuleTest::TestSimpleTimeZoneCoverage(void) {
1482 UDate time1
= getUTCMillis(1990, UCAL_JUNE
, 1);
1483 UDate time2
= getUTCMillis(2000, UCAL_JUNE
, 1);
1485 TimeZoneTransition tzt1
, tzt2
;
1486 UBool avail1
, avail2
;
1487 UErrorCode status
= U_ZERO_ERROR
;
1488 const TimeZoneRule
*trrules
[2];
1489 const InitialTimeZoneRule
*ir
= NULL
;
1492 // BasicTimeZone API implementation in SimpleTimeZone
1493 SimpleTimeZone
*stz1
= new SimpleTimeZone(-5*HOUR
, "GMT-5");
1495 avail1
= stz1
->getNextTransition(time1
, FALSE
, tzt1
);
1497 errln("FAIL: No transition must be returned by getNextTranstion for SimpleTimeZone with no DST rule");
1499 avail1
= stz1
->getPreviousTransition(time1
, FALSE
, tzt1
);
1501 errln("FAIL: No transition must be returned by getPreviousTransition for SimpleTimeZone with no DST rule");
1504 numTzRules
= stz1
->countTransitionRules(status
);
1505 if (U_FAILURE(status
)) {
1506 errln("FAIL: countTransitionRules failed");
1508 if (numTzRules
!= 0) {
1509 errln((UnicodeString
)"FAIL: countTransitionRules returned " + numTzRules
);
1512 stz1
->getTimeZoneRules(ir
, trrules
, numTzRules
, status
);
1513 if (U_FAILURE(status
)) {
1514 errln("FAIL: getTimeZoneRules failed");
1516 if (numTzRules
!= 0) {
1517 errln("FAIL: Incorrect transition rule count");
1519 if (ir
== NULL
|| ir
->getRawOffset() != stz1
->getRawOffset()) {
1520 errln("FAIL: Bad initial time zone rule");
1524 stz1
->setStartRule(UCAL_MARCH
, 11, 2*HOUR
, status
); // March 11
1525 stz1
->setEndRule(UCAL_NOVEMBER
, 1, UCAL_SUNDAY
, 2*HOUR
, status
); // First Sunday in November
1526 if (U_FAILURE(status
)) {
1527 errln("FAIL: Failed to set DST rules in a SimpleTimeZone");
1530 avail1
= stz1
->getNextTransition(time1
, FALSE
, tzt1
);
1532 errln("FAIL: Non-null transition must be returned by getNextTranstion for SimpleTimeZone with a DST rule");
1534 avail1
= stz1
->getPreviousTransition(time1
, FALSE
, tzt1
);
1536 errln("FAIL: Non-null transition must be returned by getPreviousTransition for SimpleTimeZone with a DST rule");
1539 numTzRules
= stz1
->countTransitionRules(status
);
1540 if (U_FAILURE(status
)) {
1541 errln("FAIL: countTransitionRules failed");
1543 if (numTzRules
!= 2) {
1544 errln((UnicodeString
)"FAIL: countTransitionRules returned " + numTzRules
);
1550 stz1
->getTimeZoneRules(ir
, trrules
, numTzRules
, status
);
1551 if (U_FAILURE(status
)) {
1552 errln("FAIL: getTimeZoneRules failed");
1554 if (numTzRules
!= 2) {
1555 errln("FAIL: Incorrect transition rule count");
1557 if (ir
== NULL
|| ir
->getRawOffset() != stz1
->getRawOffset()) {
1558 errln("FAIL: Bad initial time zone rule");
1560 if (trrules
[0] == NULL
|| trrules
[0]->getRawOffset() != stz1
->getRawOffset()) {
1561 errln("FAIL: Bad transition rule 0");
1563 if (trrules
[1] == NULL
|| trrules
[1]->getRawOffset() != stz1
->getRawOffset()) {
1564 errln("FAIL: Bad transition rule 1");
1567 // Set DST start year
1568 stz1
->setStartYear(2007);
1569 avail1
= stz1
->getPreviousTransition(time1
, FALSE
, tzt1
);
1571 errln("FAIL: No transition must be returned before 1990");
1573 avail1
= stz1
->getNextTransition(time1
, FALSE
, tzt1
); // transition after 1990-06-01
1574 avail2
= stz1
->getNextTransition(time2
, FALSE
, tzt2
); // transition after 2000-06-01
1575 if (!avail1
|| !avail2
|| tzt1
!= tzt2
) {
1576 errln("FAIL: Bad transition returned by SimpleTimeZone::getNextTransition");
1582 * API coverage test for VTimeZone
1585 TimeZoneRuleTest::TestVTimeZoneCoverage(void) {
1586 UErrorCode status
= U_ZERO_ERROR
;
1587 UnicodeString
TZID("Europe/Moscow");
1589 BasicTimeZone
*otz
= (BasicTimeZone
*)TimeZone::createTimeZone(TZID
);
1590 VTimeZone
*vtz
= VTimeZone::createVTimeZoneByID(TZID
);
1592 // getOffset(era, year, month, day, dayOfWeek, milliseconds, ec)
1593 int32_t offset1
= otz
->getOffset(GregorianCalendar::AD
, 2007, UCAL_JULY
, 1, UCAL_SUNDAY
, 0, status
);
1594 if (U_FAILURE(status
)) {
1595 errln("FAIL: getOffset(7 args) failed for otz");
1597 int32_t offset2
= vtz
->getOffset(GregorianCalendar::AD
, 2007, UCAL_JULY
, 1, UCAL_SUNDAY
, 0, status
);
1598 if (U_FAILURE(status
)) {
1599 errln("FAIL: getOffset(7 args) failed for vtz");
1601 if (offset1
!= offset2
) {
1602 errln("FAIL: getOffset(7 args) returned different results in VTimeZone and OlsonTimeZone");
1605 // getOffset(era, year, month, day, dayOfWeek, milliseconds, monthLength, ec)
1606 offset1
= otz
->getOffset(GregorianCalendar::AD
, 2007, UCAL_JULY
, 1, UCAL_SUNDAY
, 0, 31, status
);
1607 if (U_FAILURE(status
)) {
1608 errln("FAIL: getOffset(8 args) failed for otz");
1610 offset2
= vtz
->getOffset(GregorianCalendar::AD
, 2007, UCAL_JULY
, 1, UCAL_SUNDAY
, 0, 31, status
);
1611 if (U_FAILURE(status
)) {
1612 errln("FAIL: getOffset(8 args) failed for vtz");
1614 if (offset1
!= offset2
) {
1615 errln("FAIL: getOffset(8 args) returned different results in VTimeZone and OlsonTimeZone");
1619 // getOffset(date, local, rawOffset, dstOffset, ec)
1620 UDate t
= Calendar::getNow();
1621 int32_t rawOffset1
, dstSavings1
;
1622 int32_t rawOffset2
, dstSavings2
;
1624 otz
->getOffset(t
, FALSE
, rawOffset1
, dstSavings1
, status
);
1625 if (U_FAILURE(status
)) {
1626 errln("FAIL: getOffset(5 args) failed for otz");
1628 vtz
->getOffset(t
, FALSE
, rawOffset2
, dstSavings2
, status
);
1629 if (U_FAILURE(status
)) {
1630 errln("FAIL: getOffset(5 args) failed for vtz");
1632 if (rawOffset1
!= rawOffset2
|| dstSavings1
!= dstSavings2
) {
1633 errln("FAIL: getOffset(long,boolean,int[]) returned different results in VTimeZone and OlsonTimeZone");
1637 if (otz
->getRawOffset() != vtz
->getRawOffset()) {
1638 errln("FAIL: getRawOffset returned different results in VTimeZone and OlsonTimeZone");
1642 UBool inDst1
, inDst2
;
1643 inDst1
= otz
->inDaylightTime(t
, status
);
1644 if (U_FAILURE(status
)) {
1645 errln("FAIL: inDaylightTime failed for otz");
1647 inDst2
= vtz
->inDaylightTime(t
, status
);
1648 if (U_FAILURE(status
)) {
1649 errln("FAIL: inDaylightTime failed for vtz");
1651 if (inDst1
!= inDst2
) {
1652 errln("FAIL: inDaylightTime returned different results in VTimeZone and OlsonTimeZone");
1656 if (otz
->useDaylightTime() != vtz
->useDaylightTime()) {
1657 errln("FAIL: useDaylightTime returned different results in VTimeZone and OlsonTimeZone");
1661 const int32_t RAW
= -10*HOUR
;
1662 VTimeZone
*tmpvtz
= (VTimeZone
*)vtz
->clone();
1663 tmpvtz
->setRawOffset(RAW
);
1664 if (tmpvtz
->getRawOffset() != RAW
) {
1665 logln("setRawOffset is implemented in VTimeZone");
1669 UBool bSame
= otz
->hasSameRules(*vtz
);
1670 logln((UnicodeString
)"OlsonTimeZone::hasSameRules(VTimeZone) should return FALSE always for now - actual: " + bSame
);
1672 // getTZURL/setTZURL
1673 UnicodeString
TZURL("http://icu-project.org/timezone");
1675 if (vtz
->getTZURL(url
)) {
1676 errln("FAIL: getTZURL returned TRUE");
1678 vtz
->setTZURL(TZURL
);
1679 if (!vtz
->getTZURL(url
) || url
!= TZURL
) {
1680 errln("FAIL: URL returned by getTZURL does not match the one set by setTZURL");
1683 // getLastModified/setLastModified
1685 if (vtz
->getLastModified(lastmod
)) {
1686 errln("FAIL: getLastModified returned TRUE");
1688 vtz
->setLastModified(t
);
1689 if (!vtz
->getLastModified(lastmod
) || lastmod
!= t
) {
1690 errln("FAIL: Date returned by getLastModified does not match the one set by setLastModified");
1693 // getNextTransition/getPreviousTransition
1694 UDate base
= getUTCMillis(2007, UCAL_JULY
, 1);
1695 TimeZoneTransition tzt1
, tzt2
;
1696 UBool btr1
= otz
->getNextTransition(base
, TRUE
, tzt1
);
1697 UBool btr2
= vtz
->getNextTransition(base
, TRUE
, tzt2
);
1698 if (!btr1
|| !btr2
|| tzt1
!= tzt2
) {
1699 errln("FAIL: getNextTransition returned different results in VTimeZone and OlsonTimeZone");
1701 btr1
= otz
->getPreviousTransition(base
, FALSE
, tzt1
);
1702 btr2
= vtz
->getPreviousTransition(base
, FALSE
, tzt2
);
1703 if (!btr1
|| !btr2
|| tzt1
!= tzt2
) {
1704 errln("FAIL: getPreviousTransition returned different results in VTimeZone and OlsonTimeZone");
1707 // TimeZoneTransition constructor/clone
1708 TimeZoneTransition
*tzt1c
= tzt1
.clone();
1709 if (*tzt1c
!= tzt1
|| !(*tzt1c
== tzt1
)) {
1710 errln("FAIL: TimeZoneTransition tzt1c is equal to tzt1, but got wrong result");
1713 TimeZoneTransition
tzt3(tzt1
);
1714 if (tzt3
!= tzt1
|| !(tzt3
== tzt1
)) {
1715 errln("FAIL: TimeZoneTransition tzt3 is equal to tzt1, but got wrong result");
1718 // hasEquivalentTransitions
1719 UDate time1
= getUTCMillis(1950, UCAL_JANUARY
, 1);
1720 UDate time2
= getUTCMillis(2020, UCAL_JANUARY
, 1);
1721 UBool equiv
= vtz
->hasEquivalentTransitions(*otz
, time1
, time2
, FALSE
, status
);
1722 if (U_FAILURE(status
)) {
1723 errln("FAIL: hasEquivalentTransitions failed for vtz/otz");
1726 errln("FAIL: hasEquivalentTransitons returned false for the same time zone");
1729 // operator=/operator==/operator!=
1730 VTimeZone
*vtz1
= VTimeZone::createVTimeZoneByID("America/Los_Angeles");
1731 if (*vtz1
== *vtz
|| !(*vtz1
!= *vtz
)) {
1732 errln("FAIL: VTimeZone vtz1 is not equal to vtz, but got wrong result");
1735 if (*vtz1
!= *vtz
|| !(*vtz1
== *vtz
)) {
1736 errln("FAIL: VTimeZone vtz1 is equal to vtz, but got wrong result");
1747 TimeZoneRuleTest::TestVTimeZoneParse(void) {
1748 UErrorCode status
= U_ZERO_ERROR
;
1750 // Trying to create VTimeZone from empty data
1751 UnicodeString emptyData
;
1752 VTimeZone
*empty
= VTimeZone::createVTimeZone(emptyData
, status
);
1753 if (U_SUCCESS(status
) || empty
!= NULL
) {
1755 errln("FAIL: Non-null VTimeZone is returned for empty VTIMEZONE data");
1757 status
= U_ZERO_ERROR
;
1759 // Create VTimeZone for Asia/Tokyo
1760 UnicodeString
asiaTokyoID("Asia/Tokyo");
1761 static const UChar asiaTokyo
[] = {
1762 /* "BEGIN:VTIMEZONE\x0D\x0A" */
1763 0x42,0x45,0x47,0x49,0x4E,0x3A,0x56,0x54,0x49,0x4D,0x45,0x5A,0x4F,0x4E,0x45,0x0D,0x0A,
1764 /* "TZID:Asia\x0D\x0A" */
1765 0x54,0x5A,0x49,0x44,0x3A,0x41,0x73,0x69,0x61,0x0D,0x0A,
1766 /* "\x09/Tokyo\x0D\x0A" */
1767 0x09,0x2F,0x54,0x6F,0x6B,0x79,0x6F,0x0D,0x0A,
1768 /* "BEGIN:STANDARD\x0D\x0A" */
1769 0x42,0x45,0x47,0x49,0x4E,0x3A,0x53,0x54,0x41,0x4E,0x44,0x41,0x52,0x44,0x0D,0x0A,
1770 /* "TZOFFSETFROM:+0900\x0D\x0A" */
1771 0x54,0x5A,0x4F,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4F,0x4D,0x3A,0x2B,0x30,0x39,0x30,0x30,0x0D,0x0A,
1772 /* "TZOFFSETTO:+0900\x0D\x0A" */
1773 0x54,0x5A,0x4F,0x46,0x46,0x53,0x45,0x54,0x54,0x4F,0x3A,0x2B,0x30,0x39,0x30,0x30,0x0D,0x0A,
1774 /* "TZNAME:JST\x0D\x0A" */
1775 0x54,0x5A,0x4E,0x41,0x4D,0x45,0x3A,0x4A,0x53,0x54,0x0D,0x0A,
1776 /* "DTSTART:19700101\x0D\x0A" */
1777 0x44,0x54,0x53,0x54,0x41,0x52,0x54,0x3A,0x31,0x39,0x37,0x30,0x30,0x31,0x30,0x31,0x0D,0x0A,
1778 /* " T000000\x0D\x0A" */
1779 0x20,0x54,0x30,0x30,0x30,0x30,0x30,0x30,0x0D,0x0A,
1780 /* "END:STANDARD\x0D\x0A" */
1781 0x45,0x4E,0x44,0x3A,0x53,0x54,0x41,0x4E,0x44,0x41,0x52,0x44,0x0D,0x0A,
1782 /* "END:VTIMEZONE" */
1783 0x45,0x4E,0x44,0x3A,0x56,0x54,0x49,0x4D,0x45,0x5A,0x4F,0x4E,0x45,
1786 VTimeZone
*tokyo
= VTimeZone::createVTimeZone(asiaTokyo
, status
);
1787 if (U_FAILURE(status
) || tokyo
== NULL
) {
1788 errln("FAIL: Failed to create a VTimeZone tokyo");
1793 if (tzid
!= asiaTokyoID
) {
1794 errln((UnicodeString
)"FAIL: Invalid TZID: " + tzid
);
1796 // Make sure offsets are correct
1797 int32_t rawOffset
, dstSavings
;
1798 tokyo
->getOffset(Calendar::getNow(), FALSE
, rawOffset
, dstSavings
, status
);
1799 if (U_FAILURE(status
)) {
1800 errln("FAIL: getOffset failed for tokyo");
1802 if (rawOffset
!= 9*HOUR
|| dstSavings
!= 0) {
1803 errln("FAIL: Bad offsets returned by a VTimeZone created for Tokyo");
1808 // Create VTimeZone from VTIMEZONE data
1809 static const UChar fooData
[] = {
1810 /* "BEGIN:VCALENDAR\x0D\x0A" */
1811 0x42,0x45,0x47,0x49,0x4E,0x3A,0x56,0x43,0x41,0x4C,0x45,0x4E,0x44,0x41,0x52,0x0D,0x0A,
1812 /* "BEGIN:VTIMEZONE\x0D\x0A" */
1813 0x42,0x45,0x47,0x49,0x4E,0x3A,0x56,0x54,0x49,0x4D,0x45,0x5A,0x4F,0x4E,0x45,0x0D,0x0A,
1814 /* "TZID:FOO\x0D\x0A" */
1815 0x54,0x5A,0x49,0x44,0x3A,0x46,0x4F,0x4F,0x0D,0x0A,
1816 /* "BEGIN:STANDARD\x0D\x0A" */
1817 0x42,0x45,0x47,0x49,0x4E,0x3A,0x53,0x54,0x41,0x4E,0x44,0x41,0x52,0x44,0x0D,0x0A,
1818 /* "TZOFFSETFROM:-0700\x0D\x0A" */
1819 0x54,0x5A,0x4F,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4F,0x4D,0x3A,0x2D,0x30,0x37,0x30,0x30,0x0D,0x0A,
1820 /* "TZOFFSETTO:-0800\x0D\x0A" */
1821 0x54,0x5A,0x4F,0x46,0x46,0x53,0x45,0x54,0x54,0x4F,0x3A,0x2D,0x30,0x38,0x30,0x30,0x0D,0x0A,
1822 /* "TZNAME:FST\x0D\x0A" */
1823 0x54,0x5A,0x4E,0x41,0x4D,0x45,0x3A,0x46,0x53,0x54,0x0D,0x0A,
1824 /* "DTSTART:20071010T010000\x0D\x0A" */
1825 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,
1826 /* "RRULE:FREQ=YEARLY;BYDAY=WE;BYMONTHDAY=10,11,12,13,14,15,16;BYMONTH=10\x0D\x0A" */
1827 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,
1828 /* "END:STANDARD\x0D\x0A" */
1829 0x45,0x4E,0x44,0x3A,0x53,0x54,0x41,0x4E,0x44,0x41,0x52,0x44,0x0D,0x0A,
1830 /* "BEGIN:DAYLIGHT\x0D\x0A" */
1831 0x42,0x45,0x47,0x49,0x4E,0x3A,0x44,0x41,0x59,0x4C,0x49,0x47,0x48,0x54,0x0D,0x0A,
1832 /* "TZOFFSETFROM:-0800\x0D\x0A" */
1833 0x54,0x5A,0x4F,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4F,0x4D,0x3A,0x2D,0x30,0x38,0x30,0x30,0x0D,0x0A,
1834 /* "TZOFFSETTO:-0700\x0D\x0A" */
1835 0x54,0x5A,0x4F,0x46,0x46,0x53,0x45,0x54,0x54,0x4F,0x3A,0x2D,0x30,0x37,0x30,0x30,0x0D,0x0A,
1836 /* "TZNAME:FDT\x0D\x0A" */
1837 0x54,0x5A,0x4E,0x41,0x4D,0x45,0x3A,0x46,0x44,0x54,0x0D,0x0A,
1838 /* "DTSTART:20070415T010000\x0D\x0A" */
1839 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,
1840 /* "RRULE:FREQ=YEARLY;BYMONTHDAY=15;BYMONTH=4\x0D\x0A" */
1841 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,
1842 /* "END:DAYLIGHT\x0D\x0A" */
1843 0x45,0x4E,0x44,0x3A,0x44,0x41,0x59,0x4C,0x49,0x47,0x48,0x54,0x0D,0x0A,
1844 /* "END:VTIMEZONE\x0D\x0A" */
1845 0x45,0x4E,0x44,0x3A,0x56,0x54,0x49,0x4D,0x45,0x5A,0x4F,0x4E,0x45,0x0D,0x0A,
1846 /* "END:VCALENDAR" */
1847 0x45,0x4E,0x44,0x3A,0x56,0x43,0x41,0x4C,0x45,0x4E,0x44,0x41,0x52,
1851 VTimeZone
*foo
= VTimeZone::createVTimeZone(fooData
, status
);
1852 if (U_FAILURE(status
) || foo
== NULL
) {
1853 errln("FAIL: Failed to create a VTimeZone foo");
1855 // Write VTIMEZONE data
1856 UnicodeString fooData2
;
1857 foo
->write(getUTCMillis(2005, UCAL_JANUARY
, 1), fooData2
, status
);
1858 if (U_FAILURE(status
)) {
1859 errln("FAIL: Failed to write VTIMEZONE data for foo");
1867 TimeZoneRuleTest::TestT6216(void) {
1868 // Test case in #6216
1869 static const UChar tokyoTZ
[] = {
1870 /* "BEGIN:VCALENDAR\r\n" */
1871 0x42,0x45,0x47,0x49,0x4e,0x3a,0x56,0x43,0x41,0x4c,0x45,0x4e,0x44,0x41,0x52,0x0d,0x0a,
1872 /* "VERSION:2.0\r\n" */
1873 0x56,0x45,0x52,0x53,0x49,0x4f,0x4e,0x3a,0x32,0x2e,0x30,0x0d,0x0a,
1874 /* "PRODID:-//PYVOBJECT//NONSGML Version 1//EN\r\n" */
1875 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,
1876 /* "BEGIN:VTIMEZONE\r\n" */
1877 0x42,0x45,0x47,0x49,0x4e,0x3a,0x56,0x54,0x49,0x4d,0x45,0x5a,0x4f,0x4e,0x45,0x0d,0x0a,
1878 /* "TZID:Asia/Tokyo\r\n" */
1879 0x54,0x5a,0x49,0x44,0x3a,0x41,0x73,0x69,0x61,0x2f,0x54,0x6f,0x6b,0x79,0x6f,0x0d,0x0a,
1880 /* "BEGIN:STANDARD\r\n" */
1881 0x42,0x45,0x47,0x49,0x4e,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a,
1882 /* "DTSTART:20000101T000000\r\n" */
1883 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,
1884 /* "RRULE:FREQ=YEARLY;BYMONTH=1\r\n" */
1885 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,
1886 /* "TZNAME:Asia/Tokyo\r\n" */
1887 0x54,0x5a,0x4e,0x41,0x4d,0x45,0x3a,0x41,0x73,0x69,0x61,0x2f,0x54,0x6f,0x6b,0x79,0x6f,0x0d,0x0a,
1888 /* "TZOFFSETFROM:+0900\r\n" */
1889 0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4f,0x4d,0x3a,0x2b,0x30,0x39,0x30,0x30,0x0d,0x0a,
1890 /* "TZOFFSETTO:+0900\r\n" */
1891 0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x54,0x4f,0x3a,0x2b,0x30,0x39,0x30,0x30,0x0d,0x0a,
1892 /* "END:STANDARD\r\n" */
1893 0x45,0x4e,0x44,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a,
1894 /* "END:VTIMEZONE\r\n" */
1895 0x45,0x4e,0x44,0x3a,0x56,0x54,0x49,0x4d,0x45,0x5a,0x4f,0x4e,0x45,0x0d,0x0a,
1896 /* "END:VCALENDAR" */
1897 0x45,0x4e,0x44,0x3a,0x56,0x43,0x41,0x4c,0x45,0x4e,0x44,0x41,0x52,0x0d,0x0a,
1900 // Single final rule, overlapping with another
1901 static const UChar finalOverlap
[] = {
1902 /* "BEGIN:VCALENDAR\r\n" */
1903 0x42,0x45,0x47,0x49,0x4e,0x3a,0x56,0x43,0x41,0x4c,0x45,0x4e,0x44,0x41,0x52,0x0d,0x0a,
1904 /* "BEGIN:VTIMEZONE\r\n" */
1905 0x42,0x45,0x47,0x49,0x4e,0x3a,0x56,0x54,0x49,0x4d,0x45,0x5a,0x4f,0x4e,0x45,0x0d,0x0a,
1906 /* "TZID:FinalOverlap\r\n" */
1907 0x54,0x5a,0x49,0x44,0x3a,0x46,0x69,0x6e,0x61,0x6c,0x4f,0x76,0x65,0x72,0x6c,0x61,0x70,0x0d,0x0a,
1908 /* "BEGIN:STANDARD\r\n" */
1909 0x42,0x45,0x47,0x49,0x4e,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a,
1910 /* "TZOFFSETFROM:-0200\r\n" */
1911 0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4f,0x4d,0x3a,0x2d,0x30,0x32,0x30,0x30,0x0d,0x0a,
1912 /* "TZOFFSETTO:-0300\r\n" */
1913 0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x54,0x4f,0x3a,0x2d,0x30,0x33,0x30,0x30,0x0d,0x0a,
1914 /* "TZNAME:STD\r\n" */
1915 0x54,0x5a,0x4e,0x41,0x4d,0x45,0x3a,0x53,0x54,0x44,0x0d,0x0a,
1916 /* "DTSTART:20001029T020000\r\n" */
1917 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,
1918 /* "RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10\r\n" */
1919 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,
1920 /* "END:STANDARD\r\n" */
1921 0x45,0x4e,0x44,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a,
1922 /* "BEGIN:DAYLIGHT\r\n" */
1923 0x42,0x45,0x47,0x49,0x4e,0x3a,0x44,0x41,0x59,0x4c,0x49,0x47,0x48,0x54,0x0d,0x0a,
1924 /* "TZOFFSETFROM:-0300\r\n" */
1925 0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4f,0x4d,0x3a,0x2d,0x30,0x33,0x30,0x30,0x0d,0x0a,
1926 /* "TZOFFSETTO:-0200\r\n" */
1927 0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x54,0x4f,0x3a,0x2d,0x30,0x32,0x30,0x30,0x0d,0x0a,
1928 /* "TZNAME:DST\r\n" */
1929 0x54,0x5a,0x4e,0x41,0x4d,0x45,0x3a,0x44,0x53,0x54,0x0d,0x0a,
1930 /* "DTSTART:19990404T020000\r\n" */
1931 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,
1932 /* "RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4;UNTIL=20050403T040000Z\r\n" */
1933 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,
1934 /* "END:DAYLIGHT\r\n" */
1935 0x45,0x4e,0x44,0x3a,0x44,0x41,0x59,0x4c,0x49,0x47,0x48,0x54,0x0d,0x0a,
1936 /* "END:VTIMEZONE\r\n" */
1937 0x45,0x4e,0x44,0x3a,0x56,0x54,0x49,0x4d,0x45,0x5a,0x4f,0x4e,0x45,0x0d,0x0a,
1938 /* "END:VCALENDAR" */
1939 0x45,0x4e,0x44,0x3a,0x56,0x43,0x41,0x4c,0x45,0x4e,0x44,0x41,0x52,0x0d,0x0a,
1942 // Single final rule, no overlapping with another
1943 static const UChar finalNonOverlap
[] = {
1944 /* "BEGIN:VCALENDAR\r\n" */
1945 0x42,0x45,0x47,0x49,0x4e,0x3a,0x56,0x43,0x41,0x4c,0x45,0x4e,0x44,0x41,0x52,0x0d,0x0a,
1946 /* "BEGIN:VTIMEZONE\r\n" */
1947 0x42,0x45,0x47,0x49,0x4e,0x3a,0x56,0x54,0x49,0x4d,0x45,0x5a,0x4f,0x4e,0x45,0x0d,0x0a,
1948 /* "TZID:FinalNonOverlap\r\n" */
1949 0x54,0x5a,0x49,0x44,0x3a,0x46,0x69,0x6e,0x61,0x6c,0x4e,0x6f,0x6e,0x4f,0x76,0x65,0x72,0x6c,0x61,0x70,0x0d,0x0a,
1950 /* "BEGIN:STANDARD\r\n" */
1951 0x42,0x45,0x47,0x49,0x4e,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a,
1952 /* "TZOFFSETFROM:-0200\r\n" */
1953 0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4f,0x4d,0x3a,0x2d,0x30,0x32,0x30,0x30,0x0d,0x0a,
1954 /* "TZOFFSETTO:-0300\r\n" */
1955 0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x54,0x4f,0x3a,0x2d,0x30,0x33,0x30,0x30,0x0d,0x0a,
1956 /* "TZNAME:STD\r\n" */
1957 0x54,0x5a,0x4e,0x41,0x4d,0x45,0x3a,0x53,0x54,0x44,0x0d,0x0a,
1958 /* "DTSTART:20001029T020000\r\n" */
1959 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,
1960 /* "RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10;UNTIL=20041031T040000Z\r\n" */
1961 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,
1962 /* "END:STANDARD\r\n" */
1963 0x45,0x4e,0x44,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a,
1964 /* "BEGIN:DAYLIGHT\r\n" */
1965 0x42,0x45,0x47,0x49,0x4e,0x3a,0x44,0x41,0x59,0x4c,0x49,0x47,0x48,0x54,0x0d,0x0a,
1966 /* "TZOFFSETFROM:-0300\r\n" */
1967 0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4f,0x4d,0x3a,0x2d,0x30,0x33,0x30,0x30,0x0d,0x0a,
1968 /* "TZOFFSETTO:-0200\r\n" */
1969 0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x54,0x4f,0x3a,0x2d,0x30,0x32,0x30,0x30,0x0d,0x0a,
1970 /* "TZNAME:DST\r\n" */
1971 0x54,0x5a,0x4e,0x41,0x4d,0x45,0x3a,0x44,0x53,0x54,0x0d,0x0a,
1972 /* "DTSTART:19990404T020000\r\n" */
1973 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,
1974 /* "RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4;UNTIL=20050403T040000Z\r\n" */
1975 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,
1976 /* "END:DAYLIGHT\r\n" */
1977 0x45,0x4e,0x44,0x3a,0x44,0x41,0x59,0x4c,0x49,0x47,0x48,0x54,0x0d,0x0a,
1978 /* "BEGIN:STANDARD\r\n" */
1979 0x42,0x45,0x47,0x49,0x4e,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a,
1980 /* "TZOFFSETFROM:-0200\r\n" */
1981 0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4f,0x4d,0x3a,0x2d,0x30,0x32,0x30,0x30,0x0d,0x0a,
1982 /* "TZOFFSETTO:-0300\r\n" */
1983 0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x54,0x4f,0x3a,0x2d,0x30,0x33,0x30,0x30,0x0d,0x0a,
1984 /* "TZNAME:STDFINAL\r\n" */
1985 0x54,0x5a,0x4e,0x41,0x4d,0x45,0x3a,0x53,0x54,0x44,0x46,0x49,0x4e,0x41,0x4c,0x0d,0x0a,
1986 /* "DTSTART:20071028T020000\r\n" */
1987 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,
1988 /* "RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10\r\n" */
1989 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,
1990 /* "END:STANDARD\r\n" */
1991 0x45,0x4e,0x44,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a,
1992 /* "END:VTIMEZONE\r\n" */
1993 0x45,0x4e,0x44,0x3a,0x56,0x54,0x49,0x4d,0x45,0x5a,0x4f,0x4e,0x45,0x0d,0x0a,
1994 /* "END:VCALENDAR" */
1995 0x45,0x4e,0x44,0x3a,0x56,0x43,0x41,0x4c,0x45,0x4e,0x44,0x41,0x52,0x0d,0x0a,
1999 static const int32_t TestDates
[][3] = {
2000 {1995, UCAL_JANUARY
, 1},
2001 {1995, UCAL_JULY
, 1},
2002 {2000, UCAL_JANUARY
, 1},
2003 {2000, UCAL_JULY
, 1},
2004 {2005, UCAL_JANUARY
, 1},
2005 {2005, UCAL_JULY
, 1},
2006 {2010, UCAL_JANUARY
, 1},
2007 {2010, UCAL_JULY
, 1},
2011 static const UnicodeString TestZones
[] = {
2012 UnicodeString(tokyoTZ
),
2013 UnicodeString(finalOverlap
),
2014 UnicodeString(finalNonOverlap
),
2018 int32_t Expected
[][8] = {
2019 // JAN90 JUL90 JAN00 JUL00 JAN05 JUL05 JAN10 JUL10
2020 { 32400000, 32400000, 32400000, 32400000, 32400000, 32400000, 32400000, 32400000},
2021 {-10800000, -10800000, -7200000, -7200000, -10800000, -7200000, -10800000, -10800000},
2022 {-10800000, -10800000, -7200000, -7200000, -10800000, -7200000, -10800000, -10800000}
2028 UDate times
[sizeof(TestDates
) / (3 * sizeof(int32_t))];
2031 UErrorCode status
= U_ZERO_ERROR
;
2032 TimeZone
*utc
= TimeZone::createTimeZone("Etc/GMT");
2033 GregorianCalendar
cal(utc
, status
);
2034 if (U_FAILURE(status
)) {
2035 errln("FAIL: Failed to creat a GregorianCalendar");
2038 for (i
= 0; TestDates
[i
][2] != 0; i
++) {
2040 cal
.set(TestDates
[i
][0], TestDates
[i
][1], TestDates
[i
][2]);
2041 times
[i
] = cal
.getTime(status
);
2042 if (U_FAILURE(status
)) {
2043 errln("FAIL: getTime failed");
2050 for (i
= 0; !TestZones
[i
].isEmpty(); i
++) {
2051 VTimeZone
*vtz
= VTimeZone::createVTimeZone(TestZones
[i
], status
);
2052 if (U_FAILURE(status
)) {
2053 errln("FAIL: failed to create VTimeZone");
2056 for (j
= 0; j
< numTimes
; j
++) {
2058 status
= U_ZERO_ERROR
;
2059 vtz
->getOffset(times
[j
], FALSE
, raw
, dst
, status
);
2060 if (U_FAILURE(status
)) {
2061 errln((UnicodeString
)"FAIL: getOffset failed for time zone " + i
+ " at " + times
[j
]);
2063 int32_t offset
= raw
+ dst
;
2064 if (offset
!= Expected
[i
][j
]) {
2065 errln((UnicodeString
)"FAIL: Invalid offset at time(" + times
[j
] + "):" + offset
+ " Expected:" + Expected
[i
][j
]);
2072 //----------- private test helpers -------------------------------------------------
2075 TimeZoneRuleTest::getUTCMillis(int32_t y
, int32_t m
, int32_t d
,
2076 int32_t hr
, int32_t min
, int32_t sec
, int32_t msec
) {
2077 UErrorCode status
= U_ZERO_ERROR
;
2078 const TimeZone
*tz
= TimeZone::getGMT();
2079 Calendar
*cal
= Calendar::createInstance(*tz
, status
);
2080 if (U_FAILURE(status
)) {
2082 errln("FAIL: Calendar::createInstance failed");
2085 cal
->set(y
, m
, d
, hr
, min
, sec
);
2086 cal
->set(UCAL_MILLISECOND
, msec
);
2087 UDate utc
= cal
->getTime(status
);
2088 if (U_FAILURE(status
)) {
2090 errln("FAIL: Calendar::getTime failed");
2098 * Check if a time shift really happens on each transition returned by getNextTransition or
2099 * getPreviousTransition in the specified time range
2102 TimeZoneRuleTest::verifyTransitions(BasicTimeZone
& icutz
, UDate start
, UDate end
) {
2103 UErrorCode status
= U_ZERO_ERROR
;
2105 int32_t raw
, dst
, raw0
, dst0
;
2106 TimeZoneTransition tzt
, tzt0
;
2114 avail
= icutz
.getNextTransition(time
, FALSE
, tzt
);
2118 time
= tzt
.getTime();
2122 icutz
.getOffset(time
, FALSE
, raw
, dst
, status
);
2123 icutz
.getOffset(time
- 1, FALSE
, raw0
, dst0
, status
);
2124 if (U_FAILURE(status
)) {
2125 errln("FAIL: Error in getOffset");
2129 if (raw
== raw0
&& dst
== dst0
) {
2130 errln((UnicodeString
)"FAIL: False transition returned by getNextTransition for "
2131 + icutz
.getID(tzid
) + " at " + dateToString(time
));
2134 (tzt0
.getTo()->getRawOffset() != tzt
.getFrom()->getRawOffset()
2135 || tzt0
.getTo()->getDSTSavings() != tzt
.getFrom()->getDSTSavings())) {
2136 errln((UnicodeString
)"FAIL: TO rule of the previous transition does not match FROM rule of this transtion at "
2137 + dateToString(time
) + " for " + icutz
.getID(tzid
));
2147 avail
= icutz
.getPreviousTransition(time
, FALSE
, tzt
);
2151 time
= tzt
.getTime();
2152 if (time
<= start
) {
2155 icutz
.getOffset(time
, FALSE
, raw
, dst
, status
);
2156 icutz
.getOffset(time
- 1, FALSE
, raw0
, dst0
, status
);
2157 if (U_FAILURE(status
)) {
2158 errln("FAIL: Error in getOffset");
2162 if (raw
== raw0
&& dst
== dst0
) {
2163 errln((UnicodeString
)"FAIL: False transition returned by getPreviousTransition for "
2164 + icutz
.getID(tzid
) + " at " + dateToString(time
));
2168 (tzt0
.getFrom()->getRawOffset() != tzt
.getTo()->getRawOffset()
2169 || tzt0
.getFrom()->getDSTSavings() != tzt
.getTo()->getDSTSavings())) {
2170 errln((UnicodeString
)"FAIL: TO rule of the next transition does not match FROM rule in this transtion at "
2171 + dateToString(time
) + " for " + icutz
.getID(tzid
));
2179 * Compare all time transitions in 2 time zones in the specified time range in ascending order
2182 TimeZoneRuleTest::compareTransitionsAscending(BasicTimeZone
& z1
, BasicTimeZone
& z2
,
2183 UDate start
, UDate end
, UBool inclusive
) {
2184 UnicodeString zid1
, zid2
;
2185 TimeZoneTransition tzt1
, tzt2
;
2186 UBool avail1
, avail2
;
2187 UBool inRange1
, inRange2
;
2194 avail1
= z1
.getNextTransition(time
, inclusive
, tzt1
);
2195 avail2
= z2
.getNextTransition(time
, inclusive
, tzt2
);
2197 inRange1
= inRange2
= FALSE
;
2199 if (tzt1
.getTime() < end
|| (inclusive
&& tzt1
.getTime() == end
)) {
2204 if (tzt2
.getTime() < end
|| (inclusive
&& tzt2
.getTime() == end
)) {
2208 if (!inRange1
&& !inRange2
) {
2209 // No more transition in the range
2213 errln((UnicodeString
)"FAIL: " + zid1
+ " does not have any transitions after "
2214 + dateToString(time
) + " before " + dateToString(end
));
2218 errln((UnicodeString
)"FAIL: " + zid2
+ " does not have any transitions after "
2219 + dateToString(time
) + " before " + dateToString(end
));
2222 if (tzt1
.getTime() != tzt2
.getTime()) {
2223 errln((UnicodeString
)"FAIL: First transition after " + dateToString(time
) + " "
2224 + zid1
+ "[" + dateToString(tzt1
.getTime()) + "] "
2225 + zid2
+ "[" + dateToString(tzt2
.getTime()) + "]");
2228 time
= tzt1
.getTime();
2236 * Compare all time transitions in 2 time zones in the specified time range in descending order
2239 TimeZoneRuleTest::compareTransitionsDescending(BasicTimeZone
& z1
, BasicTimeZone
& z2
,
2240 UDate start
, UDate end
, UBool inclusive
) {
2241 UnicodeString zid1
, zid2
;
2242 TimeZoneTransition tzt1
, tzt2
;
2243 UBool avail1
, avail2
;
2244 UBool inRange1
, inRange2
;
2251 avail1
= z1
.getPreviousTransition(time
, inclusive
, tzt1
);
2252 avail2
= z2
.getPreviousTransition(time
, inclusive
, tzt2
);
2254 inRange1
= inRange2
= FALSE
;
2256 if (tzt1
.getTime() > start
|| (inclusive
&& tzt1
.getTime() == start
)) {
2261 if (tzt2
.getTime() > start
|| (inclusive
&& tzt2
.getTime() == start
)) {
2265 if (!inRange1
&& !inRange2
) {
2266 // No more transition in the range
2270 errln((UnicodeString
)"FAIL: " + zid1
+ " does not have any transitions before "
2271 + dateToString(time
) + " after " + dateToString(start
));
2275 errln((UnicodeString
)"FAIL: " + zid2
+ " does not have any transitions before "
2276 + dateToString(time
) + " after " + dateToString(start
));
2279 if (tzt1
.getTime() != tzt2
.getTime()) {
2280 errln((UnicodeString
)"FAIL: Last transition before " + dateToString(time
) + " "
2281 + zid1
+ "[" + dateToString(tzt1
.getTime()) + "] "
2282 + zid2
+ "[" + dateToString(tzt2
.getTime()) + "]");
2285 time
= tzt1
.getTime();
2292 #endif /* #if !UCONFIG_NO_FORMATTING */