1 /********************************************************************
3 * Copyright (c) 1997-2003, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
7 #include "unicode/utypes.h"
9 #if !UCONFIG_NO_FORMATTING
11 #include "unicode/timezone.h"
12 #include "unicode/simpletz.h"
13 #include "unicode/calendar.h"
14 #include "unicode/gregocal.h"
15 #include "unicode/resbund.h"
16 #include "unicode/strenum.h"
20 #define CASE(id,test) case id: \
23 logln(#test "---"); logln(""); \
28 // *****************************************************************************
30 // *****************************************************************************
32 void TimeZoneTest::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* /*par*/ )
34 if (exec
) logln("TestSuite TestTimeZone");
36 CASE(0, TestPRTOffset
);
37 CASE(1, TestVariousAPI518
);
38 CASE(2, TestGetAvailableIDs913
);
39 CASE(3, TestGenericAPI
);
41 CASE(5, TestShortZoneIDs
);
42 CASE(6, TestCustomParse
);
43 CASE(7, TestDisplayName
);
44 CASE(8, TestDSTSavings
);
45 CASE(9, TestAlternateRules
);
46 CASE(10,TestCountries
);
47 default: name
= ""; break;
51 const int32_t TimeZoneTest::millisPerHour
= 3600000;
53 // ---------------------------------------------------------------------------------
56 * Generic API testing for API coverage.
59 TimeZoneTest::TestGenericAPI()
61 UnicodeString
id("NewGMT");
62 int32_t offset
= 12345;
64 SimpleTimeZone
*zone
= new SimpleTimeZone(offset
, id
);
65 if (zone
->useDaylightTime()) errln("FAIL: useDaylightTime should return FALSE");
67 TimeZone
* zoneclone
= zone
->clone();
68 if (!(*zoneclone
== *zone
)) errln("FAIL: clone or operator== failed");
69 zoneclone
->setID("abc");
70 if (!(*zoneclone
!= *zone
)) errln("FAIL: clone or operator!= failed");
73 zoneclone
= zone
->clone();
74 if (!(*zoneclone
== *zone
)) errln("FAIL: clone or operator== failed");
75 zoneclone
->setRawOffset(45678);
76 if (!(*zoneclone
!= *zone
)) errln("FAIL: clone or operator!= failed");
78 SimpleTimeZone
copy(*zone
);
79 if (!(copy
== *zone
)) errln("FAIL: copy constructor or operator== failed");
80 copy
= *(SimpleTimeZone
*)zoneclone
;
81 if (!(copy
== *zoneclone
)) errln("FAIL: assignment operator or operator== failed");
83 TimeZone
* saveDefault
= TimeZone::createDefault();
84 TimeZone
* pstZone
= TimeZone::createTimeZone("PST");
86 logln("call u_t_timezone() which uses the host");
87 logln("to get the difference in seconds between coordinated universal");
88 logln("time and local time. E.g., -28,800 for PST (GMT-8hrs)");
90 int32_t tzoffset
= uprv_timezone();
91 logln(UnicodeString("Value returned from t_timezone = ") + tzoffset
);
92 // Invert sign because UNIX semantics are backwards
95 // --- The following test would fail outside PST now that
96 // --- PST is generally set to be default timezone in format tests
97 //if ((*saveDefault == *pstZone) && (tzoffset != 28800)) {
98 // errln("FAIL: t_timezone may be incorrect. It is not 28800");
101 if (tzoffset
!= 28800) {
102 logln("***** WARNING: If testing in the PST timezone, t_timezone should return 28800! *****");
104 if ((tzoffset
% 1800 != 0)) {
105 errln("FAIL: t_timezone may be incorrect. It is not a multiple of 30min. It is %d", tzoffset
);
108 TimeZone::adoptDefault(zone
);
109 TimeZone
* defaultzone
= TimeZone::createDefault();
110 if (defaultzone
== zone
||
111 !(*defaultzone
== *zone
))
112 errln("FAIL: createDefault failed");
113 TimeZone::adoptDefault(saveDefault
);
119 // ---------------------------------------------------------------------------------
122 * Test the setStartRule/setEndRule API calls.
125 TimeZoneTest::TestRuleAPI()
127 UErrorCode status
= U_ZERO_ERROR
;
129 UDate offset
= 60*60*1000*1.75; // Pick a weird offset
130 SimpleTimeZone
*zone
= new SimpleTimeZone((int32_t)offset
, "TestZone");
131 if (zone
->useDaylightTime()) errln("FAIL: useDaylightTime should return FALSE");
133 // Establish our expected transition times. Do this with a non-DST
134 // calendar with the (above) declared local offset.
135 GregorianCalendar
*gc
= new GregorianCalendar(*zone
, status
);
136 if (failure(status
, "new GregorianCalendar")) return;
138 gc
->set(1990, UCAL_MARCH
, 1);
139 UDate marchOneStd
= gc
->getTime(status
); // Local Std time midnight
141 gc
->set(1990, UCAL_JULY
, 1);
142 UDate julyOneStd
= gc
->getTime(status
); // Local Std time midnight
143 if (failure(status
, "GregorianCalendar::getTime")) return;
145 // Starting and ending hours, WALL TIME
146 int32_t startHour
= (int32_t)(2.25 * 3600000);
147 int32_t endHour
= (int32_t)(3.5 * 3600000);
149 zone
->setStartRule(UCAL_MARCH
, 1, 0, startHour
, status
);
150 zone
->setEndRule (UCAL_JULY
, 1, 0, endHour
, status
);
153 gc
= new GregorianCalendar(*zone
, status
);
154 if (failure(status
, "new GregorianCalendar")) return;
156 UDate marchOne
= marchOneStd
+ startHour
;
157 UDate julyOne
= julyOneStd
+ endHour
- 3600000; // Adjust from wall to Std time
159 UDate expMarchOne
= 636251400000.0;
160 if (marchOne
!= expMarchOne
)
162 errln((UnicodeString
)"FAIL: Expected start computed as " + marchOne
+
163 " = " + dateToString(marchOne
));
164 logln((UnicodeString
)" Should be " + expMarchOne
+
165 " = " + dateToString(expMarchOne
));
168 UDate expJulyOne
= 646793100000.0;
169 if (julyOne
!= expJulyOne
)
171 errln((UnicodeString
)"FAIL: Expected start computed as " + julyOne
+
172 " = " + dateToString(julyOne
));
173 logln((UnicodeString
)" Should be " + expJulyOne
+
174 " = " + dateToString(expJulyOne
));
177 testUsingBinarySearch(zone
, date(90, UCAL_JANUARY
, 1), date(90, UCAL_JUNE
, 15), marchOne
);
178 testUsingBinarySearch(zone
, date(90, UCAL_JUNE
, 1), date(90, UCAL_DECEMBER
, 31), julyOne
);
180 if (zone
->inDaylightTime(marchOne
- 1000, status
) ||
181 !zone
->inDaylightTime(marchOne
, status
))
182 errln("FAIL: Start rule broken");
183 if (!zone
->inDaylightTime(julyOne
- 1000, status
) ||
184 zone
->inDaylightTime(julyOne
, status
))
185 errln("FAIL: End rule broken");
187 zone
->setStartYear(1991);
188 if (zone
->inDaylightTime(marchOne
, status
) ||
189 zone
->inDaylightTime(julyOne
- 1000, status
))
190 errln("FAIL: Start year broken");
192 failure(status
, "TestRuleAPI");
198 TimeZoneTest::testUsingBinarySearch(SimpleTimeZone
* tz
, UDate min
, UDate max
, UDate expectedBoundary
)
200 UErrorCode status
= U_ZERO_ERROR
;
201 UBool startsInDST
= tz
->inDaylightTime(min
, status
);
202 if (failure(status
, "SimpleTimeZone::inDaylightTime")) return;
203 if (tz
->inDaylightTime(max
, status
) == startsInDST
) {
204 logln("Error: inDaylightTime(" + dateToString(max
) + ") != " + ((!startsInDST
)?"TRUE":"FALSE"));
207 if (failure(status
, "SimpleTimeZone::inDaylightTime")) return;
208 while ((max
- min
) > INTERVAL
) {
209 UDate mid
= (min
+ max
) / 2;
210 if (tz
->inDaylightTime(mid
, status
) == startsInDST
) {
216 if (failure(status
, "SimpleTimeZone::inDaylightTime")) return;
218 logln(UnicodeString("Binary Search Before: ") + uprv_floor(0.5 + min
) + " = " + dateToString(min
));
219 logln(UnicodeString("Binary Search After: ") + uprv_floor(0.5 + max
) + " = " + dateToString(max
));
220 UDate mindelta
= expectedBoundary
- min
;
221 UDate maxdelta
= max
- expectedBoundary
;
223 mindelta
<= INTERVAL
&&
225 maxdelta
<= INTERVAL
)
226 logln(UnicodeString("PASS: Expected bdry: ") + expectedBoundary
+ " = " + dateToString(expectedBoundary
));
228 errln(UnicodeString("FAIL: Expected bdry: ") + expectedBoundary
+ " = " + dateToString(expectedBoundary
));
231 const UDate
TimeZoneTest::INTERVAL
= 100;
233 // ---------------------------------------------------------------------------------
235 // -------------------------------------
238 * Test the offset of the PRT timezone.
241 TimeZoneTest::TestPRTOffset()
243 TimeZone
* tz
= TimeZone::createTimeZone("PRT");
245 errln("FAIL: TimeZone(PRT) is null");
248 if (tz
->getRawOffset() != (- 4 * millisPerHour
)) errln("FAIL: Offset for PRT should be -4");
253 // -------------------------------------
256 * Regress a specific bug with a sequence of API calls.
259 TimeZoneTest::TestVariousAPI518()
261 UErrorCode status
= U_ZERO_ERROR
;
262 TimeZone
* time_zone
= TimeZone::createTimeZone("PST");
263 UDate d
= date(97, UCAL_APRIL
, 30);
265 logln("The timezone is " + time_zone
->getID(str
));
266 if (!time_zone
->inDaylightTime(d
, status
)) errln("FAIL: inDaylightTime returned FALSE");
267 if (U_FAILURE(status
)) { errln("FAIL: TimeZone::inDaylightTime failed"); return; }
268 if (!time_zone
->useDaylightTime()) errln("FAIL: useDaylightTime returned FALSE");
269 if (time_zone
->getRawOffset() != - 8 * millisPerHour
) errln("FAIL: getRawOffset returned wrong value");
270 GregorianCalendar
*gc
= new GregorianCalendar(status
);
271 if (U_FAILURE(status
)) { errln("FAIL: Couldn't create GregorianCalendar"); return; }
272 gc
->setTime(d
, status
);
273 if (U_FAILURE(status
)) { errln("FAIL: GregorianCalendar::setTime failed"); return; }
274 if (time_zone
->getOffset(gc
->AD
, gc
->get(UCAL_YEAR
, status
), gc
->get(UCAL_MONTH
, status
),
275 gc
->get(UCAL_DATE
, status
), (uint8_t)gc
->get(UCAL_DAY_OF_WEEK
, status
), 0, status
) != - 7 * millisPerHour
)
276 errln("FAIL: getOffset returned wrong value");
277 if (U_FAILURE(status
)) { errln("FAIL: GregorianCalendar::set failed"); return; }
282 // -------------------------------------
285 * Test the call which retrieves the available IDs.
288 TimeZoneTest::TestGetAvailableIDs913()
290 UErrorCode ec
= U_ZERO_ERROR
;
292 UnicodeString
*buf
= new UnicodeString("TimeZone::createEnumeration() = { ");
294 StringEnumeration
* s
= TimeZone::createEnumeration();
295 s_length
= s
->count(ec
);
297 for (i
= 0; i
< s_length
;++i
) {
298 if (i
> 0) *buf
+= ", ";
299 *buf
+= *s
->snext(ec
);
304 /* Confirm that the following zones can be retrieved: The first
305 * zone, the last zone, and one in-between. This tests the binary
306 * search through the system zone data.
309 int32_t middle
= s_length
/2;
310 for (i
=0; i
<s_length
; ++i
) {
311 const UnicodeString
* id
= s
->snext(ec
);
312 if (i
==0 || i
==middle
|| i
==(s_length
-1)) {
313 TimeZone
*z
= TimeZone::createTimeZone(*id
);
315 errln(UnicodeString("FAIL: createTimeZone(") +
317 } else if (z
->getID(str
) != *id
) {
318 errln(UnicodeString("FAIL: createTimeZone(") +
319 *id
+ ") -> zone " + str
);
321 logln(UnicodeString("OK: createTimeZone(") +
322 *id
+ ") succeeded");
330 *buf
+= "TimeZone::createEnumeration(GMT+02:00) = { ";
332 s
= TimeZone::createEnumeration(+ 2 * 60 * 60 * 1000);
333 s_length
= s
->count(ec
);
334 for (i
= 0; i
< s_length
;++i
) {
335 if (i
> 0) *buf
+= ", ";
336 *buf
+= *s
->snext(ec
);
340 TimeZone
*tz
= TimeZone::createTimeZone("PST");
341 if (tz
!= 0) logln("getTimeZone(PST) = " + tz
->getID(str
));
342 else errln("FAIL: getTimeZone(PST) = null");
344 tz
= TimeZone::createTimeZone("America/Los_Angeles");
345 if (tz
!= 0) logln("getTimeZone(America/Los_Angeles) = " + tz
->getID(str
));
346 else errln("FAIL: getTimeZone(PST) = null");
350 tz
= TimeZone::createTimeZone("NON_EXISTENT");
353 errln("FAIL: getTimeZone(NON_EXISTENT) = null");
354 else if (tz
->getID(temp
) != "GMT")
355 errln("FAIL: getTimeZone(NON_EXISTENT) = " + temp
);
364 * This test is problematic. It should really just confirm that
365 * the list of compatibility zone IDs exist and are somewhat
366 * meaningful (that is, they aren't all aliases of GMT). It goes a
367 * bit further -- it hard-codes expectations about zone behavior,
368 * when in fact zones are redefined quite frequently. ICU's build
369 * process means that it is easy to update ICU to contain the
370 * latest Olson zone data, but if a zone tested here changes, then
371 * this test will fail. I have updated the test for 1999j data,
372 * but further updates will probably be required. Note that some
373 * of the concerts listed below no longer apply -- in particular,
374 * we do NOT overwrite real UNIX zones with 3-letter IDs. There
375 * are two points of overlap as of 1999j: MET and EET. These are
376 * both real UNIX zones, so we just use the official
377 * definition. This test has been updated to reflect this.
380 * [srl - from java - 7/5/1998]
382 * Certain short zone IDs, used since 1.1.x, are incorrect.
384 * The worst of these is:
386 * "CAT" (Central African Time) should be GMT+2:00, but instead returns a
387 * zone at GMT-1:00. The zone at GMT-1:00 should be called EGT, CVT, EGST,
388 * or AZOST, depending on which zone is meant, but in no case is it CAT.
390 * Other wrong zone IDs:
392 * ECT (European Central Time) GMT+1:00: ECT is Ecuador Time,
393 * GMT-5:00. European Central time is abbreviated CEST.
395 * SST (Solomon Island Time) GMT+11:00. SST is actually Samoa Standard Time,
396 * GMT-11:00. Solomon Island time is SBT.
398 * NST (New Zealand Time) GMT+12:00. NST is the abbreviation for
399 * Newfoundland Standard Time, GMT-3:30. New Zealanders use NZST.
401 * AST (Alaska Standard Time) GMT-9:00. [This has already been noted in
402 * another bug.] It should be "AKST". AST is Atlantic Standard Time,
405 * PNT (Phoenix Time) GMT-7:00. PNT usually means Pitcairn Time,
406 * GMT-8:30. There is no standard abbreviation for Phoenix time, as distinct
407 * from MST with daylight savings.
409 * In addition to these problems, a number of zones are FAKE. That is, they
410 * don't match what people use in the real world.
414 * EET (should be EEST)
415 * ART (should be EEST)
416 * MET (should be IRST)
417 * NET (should be AMST)
418 * PLT (should be PKT)
419 * BST (should be BDT)
420 * VST (should be ICT)
421 * CTT (should be CST) +
422 * ACT (should be CST) +
423 * AET (should be EST) +
424 * MIT (should be WST) +
425 * IET (should be EST) +
426 * PRT (should be AST) +
427 * CNT (should be NST)
428 * AGT (should be ARST)
429 * BET (should be EST) +
431 * + A zone with the correct name already exists and means something
432 * else. E.g., EST usually indicates the US Eastern zone, so it cannot be
433 * used for Brazil (BET).
435 void TimeZoneTest::TestShortZoneIDs()
438 // Create a small struct to hold the array
447 {"MIT", -660, FALSE
},
448 {"HST", -600, FALSE
},
451 {"PNT", -420, FALSE
},
454 {"IET", -300, FALSE
},
456 {"PRT", -240, FALSE
},
458 {"AGT", -180, FALSE
}, // updated 26 Sep 2000 aliu
460 // "CAT", -60, FALSE, // Wrong:
461 // As of bug 4130885, fix CAT (Central Africa)
462 {"CAT", 120, FALSE
}, // Africa/Harare
464 {"UTC", 0, FALSE
}, // ** srl: seems broken in C++
469 {"MET", 60, TRUE
}, // updated 12/3/99 aliu
470 {"NET", 240, TRUE
}, // updated 12/3/99 aliu
471 {"PLT", 300, TRUE
}, // updated 12/3/02 aliu; Pakistan using DST as of 2002
475 {"CTT", 480, TRUE
}, // updated 12/3/99 aliu
477 {"ACT", 570, TRUE
}, // updated 12/3/99 aliu
480 // "NST", 720, FALSE,
481 // As of bug 4130885, fix NST (New Zealand)
482 {"NST", 720, TRUE
}, // Pacific/Auckland
487 for(i
=0;kReferenceList
[i
].id
[0];i
++) {
488 UnicodeString
itsID(kReferenceList
[i
].id
);
491 TimeZone
*tz
= TimeZone::createTimeZone(itsID
);
493 errln("FAIL: Time Zone " + itsID
+ " does not exist!");
497 // Check daylight usage.
498 UBool usesDaylight
= tz
->useDaylightTime();
499 if (usesDaylight
!= kReferenceList
[i
].daylight
) {
500 errln("FAIL: Time Zone " + itsID
+ " use daylight is " +
501 (usesDaylight
?"TRUE":"FALSE") +
502 " but it should be " +
503 ((kReferenceList
[i
].daylight
)?"TRUE":"FALSE"));
508 int32_t offsetInMinutes
= tz
->getRawOffset()/60000;
509 if (offsetInMinutes
!= kReferenceList
[i
].offset
) {
510 errln("FAIL: Time Zone " + itsID
+ " raw offset is " +
512 " but it should be " + kReferenceList
[i
].offset
);
517 logln("OK: " + itsID
+
518 " useDaylightTime() & getRawOffset() as expected");
524 // OK now test compat
525 logln("Testing for compatibility zones");
527 const char* compatibilityMap
[] = {
528 // This list is copied from tz.alias. If tz.alias
529 // changes, this list must be updated. Current as of 1/31/01
530 "ACT", "Australia/Darwin",
531 "AET", "Australia/Sydney",
532 "AGT", "America/Buenos_Aires",
533 "ART", "Africa/Cairo",
534 "AST", "America/Anchorage",
535 "BET", "America/Sao_Paulo",
536 "BST", "Asia/Dhaka", // Spelling changed in 2000h
537 "CAT", "Africa/Harare",
538 "CNT", "America/St_Johns",
539 "CST", "America/Chicago",
540 "CTT", "Asia/Shanghai",
541 "EAT", "Africa/Addis_Ababa",
542 "ECT", "Europe/Paris",
543 // EET Europe/Istanbul # EET is a standard UNIX zone
544 "EST", "America/New_York",
545 "HST", "Pacific/Honolulu",
546 "IET", "America/Indianapolis",
547 "IST", "Asia/Calcutta",
549 // MET Asia/Tehran # MET is a standard UNIX zone
550 "MIT", "Pacific/Apia",
551 "MST", "America/Denver",
552 "NET", "Asia/Yerevan",
553 "NST", "Pacific/Auckland",
554 "PLT", "Asia/Karachi",
555 "PNT", "America/Phoenix",
556 "PRT", "America/Puerto_Rico",
557 "PST", "America/Los_Angeles",
558 "SST", "Pacific/Guadalcanal",
560 "VST", "Asia/Saigon",
564 for (i
=0;*compatibilityMap
[i
];i
+=2) {
567 const char *zone1
= compatibilityMap
[i
];
568 const char *zone2
= compatibilityMap
[i
+1];
570 TimeZone
*tz1
= TimeZone::createTimeZone(zone1
);
571 TimeZone
*tz2
= TimeZone::createTimeZone(zone2
);
574 errln(UnicodeString("FAIL: Could not find short ID zone ") + zone1
);
577 errln(UnicodeString("FAIL: Could not find long ID zone ") + zone2
);
581 // make NAME same so comparison will only look at the rest
582 tz2
->setID(tz1
->getID(itsID
));
585 errln("FAIL: " + UnicodeString(zone1
) +
586 " != " + UnicodeString(zone2
));
588 logln("OK: " + UnicodeString(zone1
) +
589 " == " + UnicodeString(zone2
));
599 * Utility function for TestCustomParse
601 UnicodeString
& TimeZoneTest::formatMinutes(int32_t min
, UnicodeString
& rv
)
606 if (min
< 0) { sign
= '-'; min
= -min
; }
612 rv
+= UChar(0x0030 + (h
/10));
613 rv
+= UChar(0x0030 + (h%10
));
618 rv
+= UChar(0x0030 + (min
/10));
622 rv
+= UChar(0x0030 + (min%10
));
629 * As part of the VM fix (see CCC approved RFE 4028006, bug
630 * 4044013), TimeZone.getTimeZone() has been modified to recognize
631 * generic IDs of the form GMT[+-]hh:mm, GMT[+-]hhmm, and
632 * GMT[+-]hh. Test this behavior here.
636 void TimeZoneTest::TestCustomParse()
639 const int32_t kUnparseable
= 604800; // the number of seconds in a week. More than any offset should be.
640 const UnicodeString kExpectedCustomID
= "Custom";
644 const char *customId
;
645 int32_t expectedOffset
;
649 // ID Expected offset in minutes
650 //"GMT", kUnparseable, Isn't custom. Can't test it here. [returns normal GMT]
651 {"GMT-YOUR.AD.HERE", kUnparseable
},
652 {"GMT0", kUnparseable
},
656 {"GMT+15:99", (15*60+99)},
657 {"GMT+", kUnparseable
},
658 {"GMT-", kUnparseable
},
659 {"GMT+0:", kUnparseable
},
660 {"GMT-:", kUnparseable
},
661 {"GMT-YOUR.AD.HERE", kUnparseable
},
662 {"GMT+0010", (10)}, // Interpret this as 00:10
663 {"GMT-10", (-10*60)},
665 {"GMT-3:30", (-(3*60+30))},
666 {"GMT-230", (-(2*60+30))},
670 for (i
=0; kData
[i
].customId
!= 0; i
++)
672 UnicodeString
id(kData
[i
].customId
);
673 int32_t exp
= kData
[i
].expectedOffset
;
675 TimeZone
*zone
= TimeZone::createTimeZone(id
);
676 UnicodeString itsID
, temp
;
679 logln("testing # " + formatMinutes(i
, temp
) + id
);
684 errln("FAIL: Could not createTimeZone(" + id + "). Returned NULL.");
690 if (! zone
->getID(itsID
).compare("GMT"))
693 logln(id
+ " -> generic GMT");
694 // When TimeZone.getTimeZone() can't parse the id, it
695 // returns GMT -- a dubious practice, but required for
696 // backward compatibility.
697 if (exp
!= kUnparseable
) {
698 errln("FAIL: Expected offset of " + formatMinutes(exp
,temp
) +
699 " for " + id
+ ", got parse failure");
705 int32_t ioffset
= zone
->getRawOffset()/60000;
706 UnicodeString offset
;
707 formatMinutes(ioffset
, offset
);
708 logln(id
+ " -> " + itsID
+ " GMT" + offset
);
709 if (exp
== kUnparseable
)
711 errln("FAIL: Expected parse failure for " + id
+
712 ", got offset of " + offset
+
715 else if (ioffset
!= exp
||
716 (itsID
.compare(kExpectedCustomID
) != 0))
718 errln("Expected offset of " + formatMinutes(exp
,temp
) +
719 ", id Custom, for " + id
+
720 ", got offset of " + offset
+
729 * Test the basic functionality of the getDisplayName() API.
734 * See also API change request A41.
736 * 4/21/98 - make smarter, so the test works if the ext resources
737 * are present or not.
740 TimeZoneTest::TestDisplayName()
742 UErrorCode status
= U_ZERO_ERROR
;
744 TimeZone
*zone
= TimeZone::createTimeZone("PST");
746 zone
->getDisplayName(Locale::getEnglish(), name
);
747 logln("PST->" + name
);
748 if (name
.compare("Pacific Standard Time") != 0)
749 errln("Fail: Expected \"Pacific Standard Time\" but got " + name
);
751 //*****************************************************************
752 // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES
753 // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES
754 // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES
755 //*****************************************************************
759 TimeZone::EDisplayType style
;
762 {FALSE
, TimeZone::SHORT
, "PST"},
763 {TRUE
, TimeZone::SHORT
, "PDT"},
764 {FALSE
, TimeZone::LONG
, "Pacific Standard Time"},
765 {TRUE
, TimeZone::LONG
, "Pacific Daylight Time"},
767 {FALSE
, TimeZone::LONG
, ""}
770 for (i
=0; kData
[i
].expect
[0] != '\0'; i
++)
773 name
= zone
->getDisplayName(kData
[i
].useDst
,
775 Locale::getEnglish(), name
);
776 if (name
.compare(kData
[i
].expect
) != 0)
777 errln("Fail: Expected " + UnicodeString(kData
[i
].expect
) + "; got " + name
);
778 logln("PST [with options]->" + name
);
780 for (i
=0; kData
[i
].expect
[0] != '\0'; i
++)
783 name
= zone
->getDisplayName(kData
[i
].useDst
,
784 kData
[i
].style
, name
);
785 if (name
.compare(kData
[i
].expect
) != 0)
786 errln("Fail: Expected " + UnicodeString(kData
[i
].expect
) + "; got " + name
);
787 logln("PST [with options]->" + name
);
791 // Make sure that we don't display the DST name by constructing a fake
792 // PST zone that has DST all year long.
793 SimpleTimeZone
*zone2
= new SimpleTimeZone(0, "PST");
795 zone2
->setStartRule(UCAL_JANUARY
, 1, 0, 0, status
);
796 zone2
->setEndRule(UCAL_DECEMBER
, 31, 0, 0, status
);
798 UnicodeString inDaylight
= (zone2
->inDaylightTime(UDate(0), status
)? UnicodeString("TRUE"):UnicodeString("FALSE"));
799 logln(UnicodeString("Modified PST inDaylightTime->") + inDaylight
);
800 if(U_FAILURE(status
))
802 errln("Some sort of error..." + UnicodeString(u_errorName(status
))); // REVISIT
805 name
= zone2
->getDisplayName(Locale::getEnglish(),name
);
806 logln("Modified PST->" + name
);
807 if (name
.compare("Pacific Standard Time") != 0)
808 errln("Fail: Expected \"Pacific Standard Time\"");
810 // Make sure we get the default display format for Locales
811 // with no display name data.
812 Locale zh_CN
= Locale::getSimplifiedChinese();
814 name
= zone
->getDisplayName(zh_CN
,name
);
815 //*****************************************************************
816 // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES
817 // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES
818 // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES
819 //*****************************************************************
820 logln("PST(zh_CN)->" + name
);
822 // *** REVISIT SRL how in the world do I check this? looks java specific.
823 // Now be smart -- check to see if zh resource is even present.
824 // If not, we expect the en fallback behavior.
825 ResourceBundle
enRB(u_getDataDirectory(),
826 Locale::getEnglish(), status
);
827 if(U_FAILURE(status
))
828 errln("Couldn't get ResourceBundle for en");
830 ResourceBundle
zhRB(u_getDataDirectory(),
832 //if(U_FAILURE(status))
833 // errln("Couldn't get ResourceBundle for zh_CN");
835 UBool noZH
= U_FAILURE(status
);
838 logln("Warning: Not testing the zh_CN behavior because resource is absent");
839 if (name
!= "Pacific Standard Time")
840 errln("Fail: Expected Pacific Standard Time");
844 if (name
.compare("GMT-08:00") &&
845 name
.compare("GMT-8:00") &&
846 name
.compare("GMT-0800") &&
847 name
.compare("GMT-800")) {
848 errln("Fail: Expected GMT-08:00 or something similar");
849 errln("************************************************************");
850 errln("THE ABOVE FAILURE MAY JUST MEAN THE LOCALE DATA HAS CHANGED");
851 errln("************************************************************");
854 // Now try a non-existent zone
856 zone2
= new SimpleTimeZone(90*60*1000, "xyzzy");
858 name
= zone2
->getDisplayName(Locale::getEnglish(),name
);
859 logln("GMT+90min->" + name
);
860 if (name
.compare("GMT+01:30") &&
861 name
.compare("GMT+1:30") &&
862 name
.compare("GMT+0130") &&
863 name
.compare("GMT+130"))
864 errln("Fail: Expected GMT+01:30 or something similar");
866 zone2
->getDisplayName(name
);
867 logln("GMT+90min->" + name
);
868 if (name
.compare("GMT+01:30") &&
869 name
.compare("GMT+1:30") &&
870 name
.compare("GMT+0130") &&
871 name
.compare("GMT+130"))
872 errln("Fail: Expected GMT+01:30 or something similar");
882 TimeZoneTest::TestDSTSavings()
884 UErrorCode status
= U_ZERO_ERROR
;
885 // It might be better to find a way to integrate this test into the main TimeZone
886 // tests above, but I don't have time to figure out how to do this (or if it's
887 // even really a good idea). Let's consider that a future. --rtg 1/27/98
888 SimpleTimeZone
*tz
= new SimpleTimeZone(-5 * U_MILLIS_PER_HOUR
, "dstSavingsTest",
889 UCAL_MARCH
, 1, 0, 0, UCAL_SEPTEMBER
, 1, 0, 0,
890 (int32_t)(0.5 * U_MILLIS_PER_HOUR
), status
);
891 if(U_FAILURE(status
))
892 errln("couldn't create TimeZone");
894 if (tz
->getRawOffset() != -5 * U_MILLIS_PER_HOUR
)
895 errln(UnicodeString("Got back a raw offset of ") + (tz
->getRawOffset() / U_MILLIS_PER_HOUR
) +
896 " hours instead of -5 hours.");
897 if (!tz
->useDaylightTime())
898 errln("Test time zone should use DST but claims it doesn't.");
899 if (tz
->getDSTSavings() != 0.5 * U_MILLIS_PER_HOUR
)
900 errln(UnicodeString("Set DST offset to 0.5 hour, but got back ") + (tz
->getDSTSavings() /
901 U_MILLIS_PER_HOUR
) + " hours instead.");
903 int32_t offset
= tz
->getOffset(GregorianCalendar::AD
, 1998, UCAL_JANUARY
, 1,
904 UCAL_THURSDAY
, 10 * U_MILLIS_PER_HOUR
,status
);
905 if (offset
!= -5 * U_MILLIS_PER_HOUR
)
906 errln(UnicodeString("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got ")
907 + (offset
/ U_MILLIS_PER_HOUR
) + " hours.");
909 offset
= tz
->getOffset(GregorianCalendar::AD
, 1998, UCAL_JUNE
, 1, UCAL_MONDAY
,
910 10 * U_MILLIS_PER_HOUR
,status
);
911 if (offset
!= -4.5 * U_MILLIS_PER_HOUR
)
912 errln(UnicodeString("The offset for 10 AM, 6/1/98 should have been -4.5 hours, but we got ")
913 + (offset
/ U_MILLIS_PER_HOUR
) + " hours.");
915 tz
->setDSTSavings(U_MILLIS_PER_HOUR
, status
);
916 offset
= tz
->getOffset(GregorianCalendar::AD
, 1998, UCAL_JANUARY
, 1,
917 UCAL_THURSDAY
, 10 * U_MILLIS_PER_HOUR
,status
);
918 if (offset
!= -5 * U_MILLIS_PER_HOUR
)
919 errln(UnicodeString("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got ")
920 + (offset
/ U_MILLIS_PER_HOUR
) + " hours.");
922 offset
= tz
->getOffset(GregorianCalendar::AD
, 1998, UCAL_JUNE
, 1, UCAL_MONDAY
,
923 10 * U_MILLIS_PER_HOUR
,status
);
924 if (offset
!= -4 * U_MILLIS_PER_HOUR
)
925 errln(UnicodeString("The offset for 10 AM, 6/1/98 (with a 1-hour DST offset) should have been -4 hours, but we got ")
926 + (offset
/ U_MILLIS_PER_HOUR
) + " hours.");
935 TimeZoneTest::TestAlternateRules()
937 // Like TestDSTSavings, this test should probably be integrated somehow with the main
938 // test at the top of this class, but I didn't have time to figure out how to do that.
941 SimpleTimeZone
tz(-5 * U_MILLIS_PER_HOUR
, "alternateRuleTest");
943 // test the day-of-month API
944 UErrorCode status
= U_ZERO_ERROR
;
945 tz
.setStartRule(UCAL_MARCH
, 10, 12 * U_MILLIS_PER_HOUR
, status
);
946 if(U_FAILURE(status
))
947 errln("tz.setStartRule failed");
948 tz
.setEndRule(UCAL_OCTOBER
, 20, 12 * U_MILLIS_PER_HOUR
, status
);
949 if(U_FAILURE(status
))
950 errln("tz.setStartRule failed");
952 int32_t offset
= tz
.getOffset(GregorianCalendar::AD
, 1998, UCAL_MARCH
, 5,
953 UCAL_THURSDAY
, 10 * U_MILLIS_PER_HOUR
,status
);
954 if (offset
!= -5 * U_MILLIS_PER_HOUR
)
955 errln(UnicodeString("The offset for 10AM, 3/5/98 should have been -5 hours, but we got ")
956 + (offset
/ U_MILLIS_PER_HOUR
) + " hours.");
958 offset
= tz
.getOffset(GregorianCalendar::AD
, 1998, UCAL_MARCH
, 15,
959 UCAL_SUNDAY
, 10 * millisPerHour
,status
);
960 if (offset
!= -4 * U_MILLIS_PER_HOUR
)
961 errln(UnicodeString("The offset for 10AM, 3/15/98 should have been -4 hours, but we got ")
962 + (offset
/ U_MILLIS_PER_HOUR
) + " hours.");
964 offset
= tz
.getOffset(GregorianCalendar::AD
, 1998, UCAL_OCTOBER
, 15,
965 UCAL_THURSDAY
, 10 * millisPerHour
,status
);
966 if (offset
!= -4 * U_MILLIS_PER_HOUR
)
967 errln(UnicodeString("The offset for 10AM, 10/15/98 should have been -4 hours, but we got ") + (offset
/ U_MILLIS_PER_HOUR
) + " hours.");
969 offset
= tz
.getOffset(GregorianCalendar::AD
, 1998, UCAL_OCTOBER
, 25,
970 UCAL_SUNDAY
, 10 * millisPerHour
,status
);
971 if (offset
!= -5 * U_MILLIS_PER_HOUR
)
972 errln(UnicodeString("The offset for 10AM, 10/25/98 should have been -5 hours, but we got ")
973 + (offset
/ U_MILLIS_PER_HOUR
) + " hours.");
975 // test the day-of-week-after-day-in-month API
976 tz
.setStartRule(UCAL_MARCH
, 10, UCAL_FRIDAY
, 12 * millisPerHour
, TRUE
, status
);
977 if(U_FAILURE(status
))
978 errln("tz.setStartRule failed");
979 tz
.setEndRule(UCAL_OCTOBER
, 20, UCAL_FRIDAY
, 12 * millisPerHour
, FALSE
, status
);
980 if(U_FAILURE(status
))
981 errln("tz.setStartRule failed");
983 offset
= tz
.getOffset(GregorianCalendar::AD
, 1998, UCAL_MARCH
, 11,
984 UCAL_WEDNESDAY
, 10 * millisPerHour
,status
);
985 if (offset
!= -5 * U_MILLIS_PER_HOUR
)
986 errln(UnicodeString("The offset for 10AM, 3/11/98 should have been -5 hours, but we got ")
987 + (offset
/ U_MILLIS_PER_HOUR
) + " hours.");
989 offset
= tz
.getOffset(GregorianCalendar::AD
, 1998, UCAL_MARCH
, 14,
990 UCAL_SATURDAY
, 10 * millisPerHour
,status
);
991 if (offset
!= -4 * U_MILLIS_PER_HOUR
)
992 errln(UnicodeString("The offset for 10AM, 3/14/98 should have been -4 hours, but we got ")
993 + (offset
/ U_MILLIS_PER_HOUR
) + " hours.");
995 offset
= tz
.getOffset(GregorianCalendar::AD
, 1998, UCAL_OCTOBER
, 15,
996 UCAL_THURSDAY
, 10 * millisPerHour
,status
);
997 if (offset
!= -4 * U_MILLIS_PER_HOUR
)
998 errln(UnicodeString("The offset for 10AM, 10/15/98 should have been -4 hours, but we got ")
999 + (offset
/ U_MILLIS_PER_HOUR
) + " hours.");
1001 offset
= tz
.getOffset(GregorianCalendar::AD
, 1998, UCAL_OCTOBER
, 17,
1002 UCAL_SATURDAY
, 10 * millisPerHour
,status
);
1003 if (offset
!= -5 * U_MILLIS_PER_HOUR
)
1004 errln(UnicodeString("The offset for 10AM, 10/17/98 should have been -5 hours, but we got ")
1005 + (offset
/ U_MILLIS_PER_HOUR
) + " hours.");
1009 * Test country code support. Jitterbug 776.
1011 void TimeZoneTest::TestCountries() {
1012 // Make sure America/Los_Angeles is in the "US" group, and
1013 // Asia/Tokyo isn't. Vice versa for the "JP" group.
1014 UErrorCode ec
= U_ZERO_ERROR
;
1016 StringEnumeration
* s
= TimeZone::createEnumeration("US");
1018 UBool la
= FALSE
, tokyo
= FALSE
;
1019 UnicodeString
laZone("America/Los_Angeles", "");
1020 UnicodeString
tokyoZone("Asia/Tokyo", "");
1023 if (s
== NULL
|| n
<= 0) {
1024 errln("FAIL: TimeZone::createEnumeration() returned nothing");
1027 for (i
=0; i
<n
; ++i
) {
1028 const UnicodeString
* id
= s
->snext(ec
);
1029 if (*id
== (laZone
)) {
1032 if (*id
== (tokyoZone
)) {
1037 errln("FAIL: " + laZone
+ " in US = " + la
);
1038 errln("FAIL: " + tokyoZone
+ " in US = " + tokyo
);
1042 s
= TimeZone::createEnumeration("JP");
1044 la
= FALSE
; tokyo
= FALSE
;
1046 for (i
=0; i
<n
; ++i
) {
1047 const UnicodeString
* id
= s
->snext(ec
);
1048 if (*id
== (laZone
)) {
1051 if (*id
== (tokyoZone
)) {
1056 errln("FAIL: " + laZone
+ " in JP = " + la
);
1057 errln("FAIL: " + tokyoZone
+ " in JP = " + tokyo
);
1059 StringEnumeration
* s1
= TimeZone::createEnumeration("US");
1060 StringEnumeration
* s2
= TimeZone::createEnumeration("US");
1062 const UnicodeString
* id1
= s1
->snext(ec
);
1063 if(id1
==NULL
|| U_FAILURE(ec
)){
1064 errln("Failed to fetch next from TimeZone enumeration. Length returned : %i Current Index: %i", n
,i
);
1066 TimeZone
* tz1
= TimeZone::createTimeZone(*id1
);
1067 for(int j
=0; j
<n
;++j
){
1068 const UnicodeString
* id2
= s2
->snext(ec
);
1069 if(id2
==NULL
|| U_FAILURE(ec
)){
1070 errln("Failed to fetch next from TimeZone enumeration. Length returned : %i Current Index: %i", n
,i
);
1072 TimeZone
* tz2
= TimeZone::createTimeZone(*id2
);
1073 if(tz1
->hasSameRules(*tz2
)){
1074 logln("ID1 : " + *id1
+" == ID2 : " +*id2
);
1085 #endif /* #if !UCONFIG_NO_FORMATTING */