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/simpletz.h"
12 #include "unicode/smpdtfmt.h"
13 #include "unicode/strenum.h"
18 // *****************************************************************************
19 // class TimeZoneRegressionTest
20 // *****************************************************************************
22 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
25 TimeZoneRegressionTest::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* /*par*/ )
27 // if (exec) logln((UnicodeString)"TestSuite NumberFormatRegressionTest");
40 CASE(10, Test4154542
);
41 CASE(11, Test4154650
);
42 CASE(12, Test4154525
);
43 CASE(13, Test4162593
);
46 CASE(16, TestJDK12API
);
48 default: name
= ""; break;
53 TimeZoneRegressionTest::failure(UErrorCode status
, const char* msg
)
55 if(U_FAILURE(status
)) {
56 errln(UnicodeString("FAIL: ") + msg
+ " failed, error " + u_errorName(status
));
66 void TimeZoneRegressionTest:: Test4052967() {
67 // {sfb} not applicable in C++ ?
68 /*logln("*** CHECK TIMEZONE AGAINST HOST OS SETTING ***");
69 logln("user.timezone:" + System.getProperty("user.timezone", "<not set>"));
70 logln(new Date().toString());
71 logln("*** THE RESULTS OF THIS TEST MUST BE VERIFIED MANUALLY ***");*/
77 void TimeZoneRegressionTest:: Test4073209() {
78 TimeZone
*z1
= TimeZone::createTimeZone("PST");
79 TimeZone
*z2
= TimeZone::createTimeZone("PST");
81 errln("Fail: TimeZone should return clones");
86 UDate
TimeZoneRegressionTest::findTransitionBinary(const SimpleTimeZone
& tz
, UDate min
, UDate max
) {
87 UErrorCode status
= U_ZERO_ERROR
;
88 UBool startsInDST
= tz
.inDaylightTime(min
, status
);
89 if (failure(status
, "SimpleTimeZone::inDaylightTime")) return 0;
90 if (tz
.inDaylightTime(max
, status
) == startsInDST
) {
91 logln((UnicodeString
)"Error: inDaylightTime() != " + ((!startsInDST
)?"TRUE":"FALSE"));
94 if (failure(status
, "SimpleTimeZone::inDaylightTime")) return 0;
95 while ((max
- min
) > 100) { // Min accuracy in ms
96 UDate mid
= (min
+ max
) / 2;
97 if (tz
.inDaylightTime(mid
, status
) == startsInDST
) {
102 if (failure(status
, "SimpleTimeZone::inDaylightTime")) return 0;
104 return (min
+ max
) / 2;
107 UDate
TimeZoneRegressionTest::findTransitionStepwise(const SimpleTimeZone
& tz
, UDate min
, UDate max
) {
108 UErrorCode status
= U_ZERO_ERROR
;
109 UBool startsInDST
= tz
.inDaylightTime(min
, status
);
110 if (failure(status
, "SimpleTimeZone::inDaylightTime")) return 0;
112 if (tz
.inDaylightTime(min
, status
) != startsInDST
) {
115 if (failure(status
, "SimpleTimeZone::inDaylightTime")) return 0;
116 min
+= (UDate
)24*60*60*1000; // one day
124 // {sfb} will this work using a Calendar?
125 void TimeZoneRegressionTest:: Test4073215()
127 UErrorCode status
= U_ZERO_ERROR
;
128 UnicodeString str
, str2
;
129 SimpleTimeZone
*z
= new SimpleTimeZone(0, "GMT");
130 if (z
->useDaylightTime())
131 errln("Fail: Fix test to start with non-DST zone");
132 z
->setStartRule(UCAL_FEBRUARY
, 1, UCAL_SUNDAY
, 0, status
);
133 failure(status
, "z->setStartRule()");
134 z
->setEndRule(UCAL_MARCH
, -1, UCAL_SUNDAY
, 0, status
);
135 failure(status
, "z->setStartRule()");
136 if (!z
->useDaylightTime())
137 errln("Fail: DST not active");
139 GregorianCalendar
cal(1997, UCAL_JANUARY
, 31, status
);
140 if(U_FAILURE(status
)) {
141 errln("Error creating calendar %s", u_errorName(status
));
144 failure(status
, "new GregorianCalendar");
145 cal
.adoptTimeZone(z
);
147 SimpleDateFormat
sdf((UnicodeString
)"E d MMM yyyy G HH:mm", status
);
148 if(U_FAILURE(status
)) {
149 errln("Error creating date format %s", u_errorName(status
));
152 sdf
.setCalendar(cal
);
153 failure(status
, "new SimpleDateFormat");
155 UDate jan31
, mar1
, mar31
;
157 UBool indt
= z
->inDaylightTime(jan31
=cal
.getTime(status
), status
);
158 failure(status
, "inDaylightTime or getTime call on Jan 31");
160 errln("Fail: Jan 31 inDaylightTime=TRUE, exp FALSE");
162 cal
.set(1997, UCAL_MARCH
, 1);
163 indt
= z
->inDaylightTime(mar1
=cal
.getTime(status
), status
);
164 failure(status
, "inDaylightTime or getTime call on Mar 1");
167 sdf
.format(cal
.getTime(status
), str
);
168 failure(status
, "getTime");
169 errln((UnicodeString
)"Fail: " + str
+ " inDaylightTime=FALSE, exp TRUE");
171 cal
.set(1997, UCAL_MARCH
, 31);
172 indt
= z
->inDaylightTime(mar31
=cal
.getTime(status
), status
);
173 failure(status
, "inDaylightTime or getTime call on Mar 31");
175 errln("Fail: Mar 31 inDaylightTime=TRUE, exp FALSE");
179 cal.set(1997, Calendar::DECEMBER, 31);
180 UDate dec31 = cal.getTime(status);
181 failure(status, "getTime");
182 UDate trans = findTransitionStepwise(*z, jan31, dec31);
183 logln((UnicodeString)"Stepwise from " +
184 sdf.format(jan31, str.remove()) + "; transition at " +
185 (trans?sdf.format(trans, str2.remove()):(UnicodeString)"NONE"));
186 trans = findTransitionStepwise(*z, mar1, dec31);
187 logln((UnicodeString)"Stepwise from " +
188 sdf.format(mar1, str.remove()) + "; transition at " +
189 (trans?sdf.format(trans, str2.remove()):(UnicodeString)"NONE"));
190 trans = findTransitionStepwise(*z, mar31, dec31);
191 logln((UnicodeString)"Stepwise from " +
192 sdf.format(mar31, str.remove()) + "; transition at " +
193 (trans?sdf.format(trans, str2.remove()):(UnicodeString)"NONE"));
199 * The expected behavior of TimeZone around the boundaries is:
200 * (Assume transition time of 2:00 AM)
201 * day of onset 1:59 AM STD = display name 1:59 AM ST
202 * 2:00 AM STD = display name 3:00 AM DT
203 * day of end 0:59 AM STD = display name 1:59 AM DT
204 * 1:00 AM STD = display name 1:00 AM ST
206 void TimeZoneRegressionTest:: Test4084933() {
207 UErrorCode status
= U_ZERO_ERROR
;
208 TimeZone
*tz
= TimeZone::createTimeZone("PST");
210 int32_t offset1
= tz
->getOffset(1,
211 1997, UCAL_OCTOBER
, 26, UCAL_SUNDAY
, (2*60*60*1000), status
);
212 int32_t offset2
= tz
->getOffset(1,
213 1997, UCAL_OCTOBER
, 26, UCAL_SUNDAY
, (2*60*60*1000)-1, status
);
215 int32_t offset3
= tz
->getOffset(1,
216 1997, UCAL_OCTOBER
, 26, UCAL_SUNDAY
, (1*60*60*1000), status
);
217 int32_t offset4
= tz
->getOffset(1,
218 1997, UCAL_OCTOBER
, 26, UCAL_SUNDAY
, (1*60*60*1000)-1, status
);
221 * The following was added just for consistency. It shows that going *to* Daylight
222 * Savings Time (PDT) does work at 2am.
225 int32_t offset5
= tz
->getOffset(1,
226 1997, UCAL_APRIL
, 6, UCAL_SUNDAY
, (2*60*60*1000), status
);
227 int32_t offset6
= tz
->getOffset(1,
228 1997, UCAL_APRIL
, 6, UCAL_SUNDAY
, (2*60*60*1000)-1, status
);
230 int32_t offset7
= tz
->getOffset(1,
231 1997, UCAL_APRIL
, 6, UCAL_SUNDAY
, (1*60*60*1000), status
);
232 int32_t offset8
= tz
->getOffset(1,
233 1997, UCAL_APRIL
, 6, UCAL_SUNDAY
, (1*60*60*1000)-1, status
);
235 int32_t SToffset
= (int32_t)(-8 * 60*60*1000L);
236 int32_t DToffset
= (int32_t)(-7 * 60*60*1000L);
237 if (offset1
!= SToffset
|| offset2
!= SToffset
||
238 offset3
!= SToffset
|| offset4
!= DToffset
||
239 offset5
!= DToffset
|| offset6
!= SToffset
||
240 offset7
!= SToffset
|| offset8
!= SToffset
241 || U_FAILURE(status
))
242 errln("Fail: TimeZone misbehaving");
250 void TimeZoneRegressionTest:: Test4096952() {
251 // {sfb} serialization not applicable
253 UnicodeString ZONES [] = { UnicodeString("GMT"), UnicodeString("MET"), UnicodeString("IST") };
256 for (int32_t i=0; i < ZONES.length; ++i) {
257 TimeZone *zone = TimeZone::createTimeZone(ZONES[i]);
259 if (zone->getID(id) != ZONES[i])
260 errln("Fail: Test broken; zones not instantiating");
262 ByteArrayOutputStream baos;
263 ObjectOutputStream ostream =
264 new ObjectOutputStream(baos = new
265 ByteArrayOutputStream());
266 ostream.writeObject(zone);
269 ObjectInputStream istream =
270 new ObjectInputStream(new
271 ByteArrayInputStream(baos.toByteArray()));
272 TimeZone frankenZone = (TimeZone) istream.readObject();
273 //logln("Zone: " + zone);
274 //logln("FrankenZone: " + frankenZone);
275 if (!zone.equals(frankenZone)) {
276 logln("TimeZone " + zone.getID() +
277 " not equal to serialized/deserialized one");
281 if (!pass) errln("Fail: TimeZone serialization/equality bug");
283 catch (IOException e) {
285 e.print32_tStackTrace();
287 catch (ClassNotFoundException e) {
289 e.print32_tStackTrace();
297 void TimeZoneRegressionTest:: Test4109314() {
298 UErrorCode status
= U_ZERO_ERROR
;
299 GregorianCalendar
*testCal
= (GregorianCalendar
*)Calendar::createInstance(status
);
300 if(U_FAILURE(status
)) {
301 errln("Error creating calendar %s", u_errorName(status
));
305 failure(status
, "Calendar::createInstance");
306 TimeZone
*PST
= TimeZone::createTimeZone("PST");
307 /*Object[] testData = {
308 PST, new Date(98,Calendar.APRIL,4,22,0), new Date(98, Calendar.APRIL, 5,6,0),
309 PST, new Date(98,Calendar.OCTOBER,24,22,0), new Date(98,Calendar.OCTOBER,25,6,0),
311 UDate testData
[] = {
312 CalendarRegressionTest::makeDate(98,UCAL_APRIL
,4,22,0),
313 CalendarRegressionTest::makeDate(98, UCAL_APRIL
,5,6,0),
314 CalendarRegressionTest::makeDate(98,UCAL_OCTOBER
,24,22,0),
315 CalendarRegressionTest::makeDate(98,UCAL_OCTOBER
,25,6,0)
318 for (int32_t i
= 0; i
< 4; i
+=2) {
319 //testCal->setTimeZone((TimeZone) testData[i]);
320 testCal
->setTimeZone(*PST
);
321 UDate t
= testData
[i
];
322 UDate end
= testData
[i
+1];
323 while(testCal
->getTime(status
) < end
) {
324 testCal
->setTime(t
, status
);
325 if ( ! checkCalendar314(testCal
, PST
))
331 errln("Fail: TZ API inconsistent");
338 TimeZoneRegressionTest::checkCalendar314(GregorianCalendar
*testCal
, TimeZone
*testTZ
)
340 UErrorCode status
= U_ZERO_ERROR
;
341 // GregorianCalendar testCal = (GregorianCalendar)aCal.clone();
343 int32_t tzOffset
, tzRawOffset
;
344 float tzOffsetFloat
,tzRawOffsetFloat
;
345 // Here is where the user made an error. They were passing in the value of
346 // the MILLSECOND field; you need to pass in the millis in the day in STANDARD
348 UDate millis
= testCal
->get(UCAL_MILLISECOND
, status
) +
349 1000.0 * (testCal
->get(UCAL_SECOND
, status
) +
350 60.0 * (testCal
->get(UCAL_MINUTE
, status
) +
351 60.0 * (testCal
->get(UCAL_HOUR_OF_DAY
, status
)))) -
352 testCal
->get(UCAL_DST_OFFSET
, status
);
354 /* Fix up millis to be in range. ASSUME THAT WE ARE NOT AT THE
355 * BEGINNING OR END OF A MONTH. We must add this code because
356 * getOffset() has been changed to be more strict about the parameters
357 * it receives -- it turns out that this test was passing in illegal
359 int32_t date
= testCal
->get(UCAL_DATE
, status
);
360 int32_t dow
= testCal
->get(UCAL_DAY_OF_WEEK
, status
);
362 millis
+= U_MILLIS_PER_DAY
;
364 dow
= UCAL_SUNDAY
+ ((dow
- UCAL_SUNDAY
+ 6) % 7);
366 while (millis
>= U_MILLIS_PER_DAY
) {
367 millis
-= U_MILLIS_PER_DAY
;
369 dow
= UCAL_SUNDAY
+ ((dow
- UCAL_SUNDAY
+ 1) % 7);
372 tzOffset
= testTZ
->getOffset((uint8_t)testCal
->get(UCAL_ERA
, status
),
373 testCal
->get(UCAL_YEAR
, status
),
374 testCal
->get(UCAL_MONTH
, status
),
379 tzRawOffset
= testTZ
->getRawOffset();
380 tzOffsetFloat
= (float)tzOffset
/(float)3600000;
381 tzRawOffsetFloat
= (float)tzRawOffset
/(float)3600000;
383 UDate testDate
= testCal
->getTime(status
);
385 UBool inDaylightTime
= testTZ
->inDaylightTime(testDate
, status
);
386 SimpleDateFormat
*sdf
= new SimpleDateFormat((UnicodeString
)"MM/dd/yyyy HH:mm", status
);
387 sdf
->setCalendar(*testCal
);
388 UnicodeString inDaylightTimeString
;
394 inDaylightTimeString
= " DST ";
395 passed
= (tzOffset
== (tzRawOffset
+ 3600000));
399 inDaylightTimeString
= " ";
400 passed
= (tzOffset
== tzRawOffset
);
403 UnicodeString output
;
404 FieldPosition
pos(0);
405 output
= testTZ
->getID(output
) + " " + sdf
->format(testDate
, output
, pos
) +
406 " Offset(" + tzOffsetFloat
+ ")" +
407 " RawOffset(" + tzRawOffsetFloat
+ ")" +
408 " " + millis
/(float)3600000 + " " +
409 inDaylightTimeString
;
429 * Yet another _alleged_ bug in TimeZone::getOffset(), a method that never
430 * should have been made public. It's simply too hard to use correctly.
432 * The original test code failed to do the following:
433 * (1) Call Calendar::setTime() before getting the fields!
434 * (2) Use the right millis (as usual) for getOffset(); they were passing
435 * in the MILLIS field, instead of the STANDARD MILLIS IN DAY.
436 * When you fix these two problems, the test passes, as expected.
438 void TimeZoneRegressionTest:: Test4126678()
440 UErrorCode status
= U_ZERO_ERROR
;
441 Calendar
*cal
= Calendar::createInstance(status
);
442 if(U_FAILURE(status
)) {
443 errln("Error creating calendar %s", u_errorName(status
));
447 failure(status
, "Calendar::createInstance");
448 TimeZone
*tz
= TimeZone::createTimeZone("PST");
449 cal
->adoptTimeZone(tz
);
451 cal
->set(1998 - 1900, UCAL_APRIL
, 5, 10, 0);
452 //Date dt = new Date(1998-1900, Calendar::APRIL, 5, 10, 0);
454 if (! tz
->useDaylightTime() || U_FAILURE(status
))
455 errln("We're not in Daylight Savings Time and we should be.\n");
458 int32_t era
= cal
->get(UCAL_ERA
, status
);
459 int32_t year
= cal
->get(UCAL_YEAR
, status
);
460 int32_t month
= cal
->get(UCAL_MONTH
, status
);
461 int32_t day
= cal
->get(UCAL_DATE
, status
);
462 int32_t dayOfWeek
= cal
->get(UCAL_DAY_OF_WEEK
, status
);
463 int32_t millis
= cal
->get(UCAL_MILLISECOND
, status
) +
464 (cal
->get(UCAL_SECOND
, status
) +
465 (cal
->get(UCAL_MINUTE
, status
) +
466 (cal
->get(UCAL_HOUR
, status
) * 60) * 60) * 1000) -
467 cal
->get(UCAL_DST_OFFSET
, status
);
469 failure(status
, "cal->get");
470 int32_t offset
= tz
->getOffset((uint8_t)era
, year
, month
, day
, (uint8_t)dayOfWeek
, millis
, status
);
471 int32_t raw_offset
= tz
->getRawOffset();
472 if (offset
== raw_offset
)
473 errln("Offsets should not match when in DST");
480 * TimeZone::getAvailableIDs(int32_t) throws exception for certain values,
481 * due to a faulty constant in TimeZone::java.
483 void TimeZoneRegressionTest:: Test4151406() {
485 for (int32_t h
=-28; h
<=30; ++h
) {
486 // h is in half-hours from GMT; rawoffset is in millis
487 int32_t rawoffset
= h
* 1800000;
488 int32_t hh
= (h
<0) ? -h
: h
;
489 UnicodeString hname
= UnicodeString((h
<0) ? "GMT-" : "GMT+") +
490 ((hh
/2 < 10) ? "0" : "") +
492 ((hh%2
==0) ? "00" : "30");
494 UErrorCode ec
= U_ZERO_ERROR
;
496 StringEnumeration
* ids
= TimeZone::createEnumeration(rawoffset
);
497 count
= ids
->count(ec
);
501 logln(hname
+ ' ' + (UnicodeString
)count
+ (UnicodeString
)" e.g. " + *ids
->snext(ec
));
503 logln(hname
+ ' ' + count
);
505 // weiv 11/27/2002: why uprv_free? This should be a delete
509 /*} catch (Exception e) {
510 errln(hname + ' ' + "Fail: " + e);
513 logln("Maximum zones per offset = %d", max
);
519 void TimeZoneRegressionTest:: Test4151429() {
520 // {sfb} silly test in C++, since we are using an enum and not an int
522 /*TimeZone *tz = TimeZone::createTimeZone("GMT");
524 tz->getDisplayName(TRUE, TimeZone::LONG,
525 Locale.getDefault(), name);
526 errln("IllegalArgumentException not thrown by TimeZone::getDisplayName()");*/
527 //} catch(IllegalArgumentException e) {}
532 * SimpleTimeZone::hasSameRules() doesn't work for zones with no DST
533 * and different DST parameters.
535 void TimeZoneRegressionTest:: Test4154537() {
536 UErrorCode status
= U_ZERO_ERROR
;
537 // tz1 and tz2 have no DST and different rule parameters
538 SimpleTimeZone
*tz1
= new SimpleTimeZone(0, "1", 0, 0, 0, 0, 2, 0, 0, 0, status
);
539 SimpleTimeZone
*tz2
= new SimpleTimeZone(0, "2", 1, 0, 0, 0, 3, 0, 0, 0, status
);
540 // tza and tzA have the same rule params
541 SimpleTimeZone
*tza
= new SimpleTimeZone(0, "a", 0, 1, 0, 0, 3, 2, 0, 0, status
);
542 SimpleTimeZone
*tzA
= new SimpleTimeZone(0, "A", 0, 1, 0, 0, 3, 2, 0, 0, status
);
543 // tzb differs from tza
544 SimpleTimeZone
*tzb
= new SimpleTimeZone(0, "b", 0, 1, 0, 0, 3, 1, 0, 0, status
);
546 if(U_FAILURE(status
))
547 errln("Couldn't create TimeZones");
549 if (tz1
->useDaylightTime() || tz2
->useDaylightTime() ||
550 !tza
->useDaylightTime() || !tzA
->useDaylightTime() ||
551 !tzb
->useDaylightTime()) {
552 errln("Test is broken -- rewrite it");
554 if (!tza
->hasSameRules(*tzA
) || tza
->hasSameRules(*tzb
)) {
555 errln("Fail: hasSameRules() broken for zones with rules");
557 if (!tz1
->hasSameRules(*tz2
)) {
558 errln("Fail: hasSameRules() returns false for zones without rules");
559 //errln("zone 1 = " + tz1);
560 //errln("zone 2 = " + tz2);
572 * SimpleTimeZOne constructors, setStartRule(), and setEndRule() don't
573 * check for out-of-range arguments.
575 void TimeZoneRegressionTest:: Test4154542()
577 const int32_t GOOD
= 1;
578 const int32_t BAD
= 0;
580 const int32_t GOOD_MONTH
= UCAL_JANUARY
;
581 const int32_t GOOD_DAY
= 1;
582 const int32_t GOOD_DAY_OF_WEEK
= UCAL_SUNDAY
;
583 const int32_t GOOD_TIME
= 0;
586 GOOD
, INT32_MIN
, 0, INT32_MAX
, INT32_MIN
,
587 GOOD
, UCAL_JANUARY
, -5, UCAL_SUNDAY
, 0,
588 GOOD
, UCAL_DECEMBER
, 5, UCAL_SATURDAY
, 24*60*60*1000,
589 BAD
, UCAL_DECEMBER
, 5, UCAL_SATURDAY
, 24*60*60*1000+1,
590 BAD
, UCAL_DECEMBER
, 5, UCAL_SATURDAY
, -1,
591 BAD
, UCAL_JANUARY
, -6, UCAL_SUNDAY
, 0,
592 BAD
, UCAL_DECEMBER
, 6, UCAL_SATURDAY
, 24*60*60*1000,
593 GOOD
, UCAL_DECEMBER
, 1, 0, 0,
594 GOOD
, UCAL_DECEMBER
, 31, 0, 0,
595 BAD
, UCAL_APRIL
, 31, 0, 0,
596 BAD
, UCAL_DECEMBER
, 32, 0, 0,
597 BAD
, UCAL_JANUARY
-1, 1, UCAL_SUNDAY
, 0,
598 BAD
, UCAL_DECEMBER
+1, 1, UCAL_SUNDAY
, 0,
599 GOOD
, UCAL_DECEMBER
, 31, -UCAL_SUNDAY
, 0,
600 GOOD
, UCAL_DECEMBER
, 31, -UCAL_SATURDAY
, 0,
601 BAD
, UCAL_DECEMBER
, 32, -UCAL_SATURDAY
, 0,
602 BAD
, UCAL_DECEMBER
, -32, -UCAL_SATURDAY
, 0,
603 BAD
, UCAL_DECEMBER
, 31, -UCAL_SATURDAY
-1, 0,
605 SimpleTimeZone
*zone
= new SimpleTimeZone(0, "Z");
606 for (int32_t i
=0; i
< 18*5; i
+=5) {
607 UBool shouldBeGood
= (DATA
[i
] == GOOD
);
608 int32_t month
= DATA
[i
+1];
609 int32_t day
= DATA
[i
+2];
610 int32_t dayOfWeek
= DATA
[i
+3];
611 int32_t time
= DATA
[i
+4];
613 UErrorCode status
= U_ZERO_ERROR
;
615 //Exception ex = null;
617 zone
->setStartRule(month
, day
, dayOfWeek
, time
, status
);
618 //} catch (IllegalArgumentException e) {
621 if (U_SUCCESS(status
) != shouldBeGood
) {
622 errln(UnicodeString("setStartRule(month=") + month
+ ", day=" + day
+
623 ", dayOfWeek=" + dayOfWeek
+ ", time=" + time
+
624 (shouldBeGood
? (") should work")
625 : ") should fail but doesn't"));
630 status
= U_ZERO_ERROR
;
631 zone
->setEndRule(month
, day
, dayOfWeek
, time
, status
);
632 //} catch (IllegalArgumentException e) {
635 if (U_SUCCESS(status
) != shouldBeGood
) {
636 errln(UnicodeString("setEndRule(month=") + month
+ ", day=" + day
+
637 ", dayOfWeek=" + dayOfWeek
+ ", time=" + time
+
638 (shouldBeGood
? (") should work")
639 : ") should fail but doesn't"));
644 // {sfb} need to look into ctor problems! (UErrorCode vs. dst signature confusion)
645 status
= U_ZERO_ERROR
;
646 SimpleTimeZone
*temp
= new SimpleTimeZone(0, "Z",
647 (int8_t)month
, (int8_t)day
, (int8_t)dayOfWeek
, time
,
648 (int8_t)GOOD_MONTH
, (int8_t)GOOD_DAY
, (int8_t)GOOD_DAY_OF_WEEK
,
650 //} catch (IllegalArgumentException e) {
653 if (U_SUCCESS(status
) != shouldBeGood
) {
654 errln(UnicodeString("SimpleTimeZone(month=") + month
+ ", day=" + day
+
655 ", dayOfWeek=" + dayOfWeek
+ ", time=" + time
+
656 (shouldBeGood
? (", <end>) should work")// + ex)
657 : ", <end>) should fail but doesn't"));
663 status
= U_ZERO_ERROR
;
664 temp
= new SimpleTimeZone(0, "Z",
665 (int8_t)GOOD_MONTH
, (int8_t)GOOD_DAY
, (int8_t)GOOD_DAY_OF_WEEK
,
667 (int8_t)month
, (int8_t)day
, (int8_t)dayOfWeek
, time
,status
);
668 //} catch (IllegalArgumentException e) {
671 if (U_SUCCESS(status
) != shouldBeGood
) {
672 errln(UnicodeString("SimpleTimeZone(<start>, month=") + month
+ ", day=" + day
+
673 ", dayOfWeek=" + dayOfWeek
+ ", time=" + time
+
674 (shouldBeGood
? (") should work")// + ex)
675 : ") should fail but doesn't"));
685 * SimpleTimeZone accepts illegal DST savings values. These values
686 * must be non-zero. There is no upper limit at this time.
689 TimeZoneRegressionTest::Test4154525()
691 const int32_t GOOD
= 1, BAD
= 0;
699 // Integer.MAX_VALUE, ?, // no upper limit on DST savings at this time
702 UErrorCode status
= U_ZERO_ERROR
;
703 for(int32_t i
= 0; i
< 10; i
+=2) {
704 int32_t savings
= DATA
[i
];
705 UBool valid
= DATA
[i
+1] == GOOD
;
706 UnicodeString method
;
707 for(int32_t j
=0; j
< 2; ++j
) {
708 SimpleTimeZone
*z
=NULL
;
711 method
= "constructor";
712 z
= new SimpleTimeZone(0, "id",
713 UCAL_JANUARY
, 1, 0, 0,
715 savings
, status
); // <- what we're interested in
718 method
= "setDSTSavings()";
719 z
= new SimpleTimeZone(0, "GMT");
720 z
->setDSTSavings(savings
, status
);
724 if(U_FAILURE(status
)) {
726 errln(UnicodeString("Fail: DST savings of ") + savings
+ " to " + method
+ " gave " + u_errorName(status
));
729 logln(UnicodeString("Pass: DST savings of ") + savings
+ " to " + method
+ " gave " + u_errorName(status
));
734 logln(UnicodeString("Pass: DST savings of ") + savings
+ " accepted by " + method
);
737 errln(UnicodeString("Fail: DST savings of ") + savings
+ " accepted by " + method
);
740 status
= U_ZERO_ERROR
;
748 * SimpleTimeZone.getOffset accepts illegal arguments.
751 TimeZoneRegressionTest::Test4154650()
753 const int32_t GOOD
= 1, BAD
= 0;
754 const int32_t GOOD_ERA
= GregorianCalendar::AD
, GOOD_YEAR
= 1998, GOOD_MONTH
= UCAL_AUGUST
;
755 const int32_t GOOD_DAY
= 2, GOOD_DOW
= UCAL_SUNDAY
, GOOD_TIME
= 16*3600000;
758 GOOD
, GOOD_ERA
, GOOD_YEAR
, GOOD_MONTH
, GOOD_DAY
, GOOD_DOW
, GOOD_TIME
,
760 GOOD
, GregorianCalendar::BC
, GOOD_YEAR
, GOOD_MONTH
, GOOD_DAY
, GOOD_DOW
, GOOD_TIME
,
761 GOOD
, GregorianCalendar::AD
, GOOD_YEAR
, GOOD_MONTH
, GOOD_DAY
, GOOD_DOW
, GOOD_TIME
,
762 BAD
, GregorianCalendar::BC
-1, GOOD_YEAR
, GOOD_MONTH
, GOOD_DAY
, GOOD_DOW
, GOOD_TIME
,
763 BAD
, GregorianCalendar::AD
+1, GOOD_YEAR
, GOOD_MONTH
, GOOD_DAY
, GOOD_DOW
, GOOD_TIME
,
765 GOOD
, GOOD_ERA
, GOOD_YEAR
, UCAL_JANUARY
, GOOD_DAY
, GOOD_DOW
, GOOD_TIME
,
766 GOOD
, GOOD_ERA
, GOOD_YEAR
, UCAL_DECEMBER
, GOOD_DAY
, GOOD_DOW
, GOOD_TIME
,
767 BAD
, GOOD_ERA
, GOOD_YEAR
, UCAL_JANUARY
-1, GOOD_DAY
, GOOD_DOW
, GOOD_TIME
,
768 BAD
, GOOD_ERA
, GOOD_YEAR
, UCAL_DECEMBER
+1, GOOD_DAY
, GOOD_DOW
, GOOD_TIME
,
770 GOOD
, GOOD_ERA
, GOOD_YEAR
, UCAL_JANUARY
, 1, GOOD_DOW
, GOOD_TIME
,
771 GOOD
, GOOD_ERA
, GOOD_YEAR
, UCAL_JANUARY
, 31, GOOD_DOW
, GOOD_TIME
,
772 BAD
, GOOD_ERA
, GOOD_YEAR
, UCAL_JANUARY
, 0, GOOD_DOW
, GOOD_TIME
,
773 BAD
, GOOD_ERA
, GOOD_YEAR
, UCAL_JANUARY
, 32, GOOD_DOW
, GOOD_TIME
,
775 GOOD
, GOOD_ERA
, GOOD_YEAR
, GOOD_MONTH
, GOOD_DAY
, UCAL_SUNDAY
, GOOD_TIME
,
776 GOOD
, GOOD_ERA
, GOOD_YEAR
, GOOD_MONTH
, GOOD_DAY
, UCAL_SATURDAY
, GOOD_TIME
,
777 BAD
, GOOD_ERA
, GOOD_YEAR
, GOOD_MONTH
, GOOD_DAY
, UCAL_SUNDAY
-1, GOOD_TIME
,
778 BAD
, GOOD_ERA
, GOOD_YEAR
, GOOD_MONTH
, GOOD_DAY
, UCAL_SATURDAY
+1, GOOD_TIME
,
780 GOOD
, GOOD_ERA
, GOOD_YEAR
, GOOD_MONTH
, GOOD_DAY
, GOOD_DOW
, 0,
781 GOOD
, GOOD_ERA
, GOOD_YEAR
, GOOD_MONTH
, GOOD_DAY
, GOOD_DOW
, 24*3600000-1,
782 BAD
, GOOD_ERA
, GOOD_YEAR
, GOOD_MONTH
, GOOD_DAY
, GOOD_DOW
, -1,
783 BAD
, GOOD_ERA
, GOOD_YEAR
, GOOD_MONTH
, GOOD_DAY
, GOOD_DOW
, 24*3600000,
786 int32_t dataLen
= (int32_t)(sizeof(DATA
) / sizeof(DATA
[0]));
788 UErrorCode status
= U_ZERO_ERROR
;
789 TimeZone
*tz
= TimeZone::createDefault();
790 for(int32_t i
= 0; i
< dataLen
; i
+= 7) {
791 UBool good
= DATA
[i
] == GOOD
;
792 //IllegalArgumentException e = null;
794 /*int32_t offset = */
795 tz
->getOffset((uint8_t)DATA
[i
+1], DATA
[i
+2], DATA
[i
+3],
796 DATA
[i
+4], (uint8_t)DATA
[i
+5], DATA
[i
+6], status
);
797 //} catch (IllegalArgumentException ex) {
800 if(good
!= U_SUCCESS(status
)) {
801 UnicodeString errMsg
;
803 errMsg
= (UnicodeString(") threw ") + u_errorName(status
));
806 errMsg
= UnicodeString(") accepts invalid args", "");
808 errln(UnicodeString("Fail: getOffset(") +
809 DATA
[i
+1] + ", " + DATA
[i
+2] + ", " + DATA
[i
+3] + ", " +
810 DATA
[i
+4] + ", " + DATA
[i
+5] + ", " + DATA
[i
+6] +
813 status
= U_ZERO_ERROR
; // reset
820 * TimeZone broken at midnight. The TimeZone code fails to handle
821 * transitions at midnight correctly.
824 TimeZoneRegressionTest::Test4162593()
826 UErrorCode status
= U_ZERO_ERROR
;
827 SimpleDateFormat
*fmt
= new SimpleDateFormat("z", Locale::getUS(), status
);
828 if(U_FAILURE(status
)) {
829 errln("Error creating calendar %s", u_errorName(status
));
833 const int32_t ONE_HOUR
= 60*60*1000;
835 SimpleTimeZone
*asuncion
= new SimpleTimeZone(-4*ONE_HOUR
, "America/Asuncion" /*PY%sT*/,
836 UCAL_OCTOBER
, 1, 0 /*DOM*/, 0*ONE_HOUR
,
837 UCAL_MARCH
, 1, 0 /*DOM*/, 0*ONE_HOUR
, 1*ONE_HOUR
, status
);
841 * Transition expected between start+1H and start+2H
843 TimeZone
*DATA_TZ
[] = {
846 int32_t DATA_INT
[] [5] = {
847 // These years must be AFTER the Gregorian cutover
848 {1998, UCAL_SEPTEMBER
, 30, 22, 0},
849 {2000, UCAL_FEBRUARY
, 28, 22, 0},
850 {2000, UCAL_FEBRUARY
, 29, 22, 0},
853 UBool DATA_BOOL
[] = {
859 UnicodeString zone
[4];// = new String[4];
861 new SimpleTimeZone(2*ONE_HOUR
, "Asia/Damascus" /*EE%sT*/,
862 UCAL_APRIL
, 1, 0 /*DOM*/, 0*ONE_HOUR
,
863 UCAL_OCTOBER
, 1, 0 /*DOM*/, 0*ONE_HOUR
, 1*ONE_HOUR
, status
);
864 DATA_TZ
[1] = asuncion
; DATA_TZ
[2] = asuncion
;
866 for(int32_t j
= 0; j
< 3; j
++) {
867 TimeZone
*tz
= (TimeZone
*)DATA_TZ
[j
];
868 TimeZone::setDefault(*tz
);
869 fmt
->setTimeZone(*tz
);
871 // Must construct the Date object AFTER setting the default zone
872 int32_t *p
= (int32_t*)DATA_INT
[j
];
873 UDate d
= CalendarRegressionTest::makeDate(p
[0], p
[1], p
[2], p
[3], p
[4]);
874 UBool transitionExpected
= DATA_BOOL
[j
];
877 logln(tz
->getID(temp
) + ":");
878 for (int32_t i
= 0; i
< 4; ++i
) {
879 FieldPosition
pos(0);
881 zone
[i
] = fmt
->format(d
, zone
[i
], pos
);
882 logln(UnicodeString("") + i
+ ": " + d
+ " / " + zone
[i
]);
883 d
+= (double) ONE_HOUR
;
885 if(zone
[0] == zone
[1] &&
886 (zone
[1] == zone
[2]) != transitionExpected
&&
887 zone
[2] == zone
[3]) {
888 logln(UnicodeString("Ok: transition ") + transitionExpected
);
891 errln("Fail: boundary transition incorrect");
900 * Make sure setStartRule and setEndRule set the DST savings to nonzero
903 void TimeZoneRegressionTest::TestJ186() {
904 UErrorCode status
= U_ZERO_ERROR
;
905 // NOTE: Setting the DST savings to zero is illegal, so we
906 // are limited in the testing we can do here. This is why
907 // lines marked //~ are commented out.
908 SimpleTimeZone
z(0, "ID");
909 //~z.setDSTSavings(0, status); // Must do this!
910 z
.setStartRule(UCAL_FEBRUARY
, 1, UCAL_SUNDAY
, 0, status
);
911 failure(status
, "setStartRule()");
912 if (z
.useDaylightTime()) {
913 errln("Fail: useDaylightTime true with start rule only");
915 //~if (z.getDSTSavings() != 0) {
916 //~ errln("Fail: dst savings != 0 with start rule only");
918 z
.setEndRule(UCAL_MARCH
, -1, UCAL_SUNDAY
, 0, status
);
919 failure(status
, "setStartRule()");
920 if (!z
.useDaylightTime()) {
921 errln("Fail: useDaylightTime false with rules set");
923 if (z
.getDSTSavings() == 0) {
924 errln("Fail: dst savings == 0 with rules set");
929 * Test to see if DateFormat understands zone equivalency groups. It
930 * might seem that this should be a DateFormat test, but it's really a
931 * TimeZone test -- the changes to DateFormat are minor.
933 * We use two known, stable zones that shouldn't change much over time
934 * -- America/Vancouver and America/Los_Angeles. However, they MAY
935 * change at some point -- if that happens, replace them with any two
936 * zones in an equivalency group where one zone has localized name
937 * data, and the other doesn't, in some locale.
939 void TimeZoneRegressionTest::TestJ449() {
940 UErrorCode status
= U_ZERO_ERROR
;
943 // Modify the following three as necessary. The two IDs must
944 // specify two zones in the same equivalency group. One must have
945 // locale data in 'loc'; the other must not.
946 const char* idWithLocaleData
= "America/Los_Angeles";
947 const char* idWithoutLocaleData
= "US/Pacific";
948 const Locale
loc("en", "", "");
950 TimeZone
*zoneWith
= TimeZone::createTimeZone(idWithLocaleData
);
951 TimeZone
*zoneWithout
= TimeZone::createTimeZone(idWithoutLocaleData
);
952 // Make sure we got valid zones
953 if (zoneWith
->getID(str
) != UnicodeString(idWithLocaleData
) ||
954 zoneWithout
->getID(str
) != UnicodeString(idWithoutLocaleData
)) {
955 errln(UnicodeString("Fail: Unable to create zones - wanted ") + idWithLocaleData
+ ", got " + zoneWith
->getID(str
) + ", and wanted " + idWithoutLocaleData
+ " but got " + zoneWithout
->getID(str
));
957 GregorianCalendar
calWith(*zoneWith
, status
);
958 GregorianCalendar
calWithout(*zoneWithout
, status
);
959 SimpleDateFormat
fmt("MMM d yyyy hh:mm a zzz", loc
, status
);
960 if (U_FAILURE(status
)) {
961 errln("Fail: Unable to create GregorianCalendar/SimpleDateFormat");
964 UnicodeString strWith
, strWithout
;
965 fmt
.setCalendar(calWith
);
966 fmt
.format(date
, strWith
);
967 fmt
.setCalendar(calWithout
);
968 fmt
.format(date
, strWithout
);
969 if (strWith
== strWithout
) {
970 logln((UnicodeString
)"Ok: " + idWithLocaleData
+ " -> " +
971 strWith
+ "; " + idWithoutLocaleData
+ " -> " +
974 errln((UnicodeString
)"FAIL: " + idWithLocaleData
+ " -> " +
975 strWith
+ "; " + idWithoutLocaleData
+ " -> " +
985 // test new API for JDK 1.2 8/31 putback
987 TimeZoneRegressionTest::TestJDK12API()
989 // TimeZone *pst = TimeZone::createTimeZone("PST");
990 // TimeZone *cst1 = TimeZone::createTimeZone("CST");
991 UErrorCode ec
= U_ZERO_ERROR
;
992 //d,-28800,3,1,-1,120,w,9,-1,1,120,w,60
993 TimeZone
*pst
= new SimpleTimeZone(-28800*U_MILLIS_PER_SECOND
,
995 3,1,-1,120*U_MILLIS_PER_MINUTE
,
996 SimpleTimeZone::WALL_TIME
,
997 9,-1,1,120*U_MILLIS_PER_MINUTE
,
998 SimpleTimeZone::WALL_TIME
,
999 60*U_MILLIS_PER_MINUTE
,ec
);
1000 //d,-21600,3,1,-1,120,w,9,-1,1,120,w,60
1001 TimeZone
*cst1
= new SimpleTimeZone(-21600*U_MILLIS_PER_SECOND
,
1003 3,1,-1,120*U_MILLIS_PER_MINUTE
,
1004 SimpleTimeZone::WALL_TIME
,
1005 9,-1,1,120*U_MILLIS_PER_MINUTE
,
1006 SimpleTimeZone::WALL_TIME
,
1007 60*U_MILLIS_PER_MINUTE
,ec
);
1008 if (U_FAILURE(ec
)) {
1009 errln("FAIL: SimpleTimeZone constructor");
1013 SimpleTimeZone
*cst
= 0;
1015 if(cst1
->getDynamicClassID() == SimpleTimeZone::getStaticClassID())
1016 cst
= (SimpleTimeZone
*) cst1
;
1018 if(pst
->hasSameRules(*cst
)) {
1019 errln("FAILURE: PST and CST have same rules");
1022 UErrorCode status
= U_ZERO_ERROR
;
1023 int32_t offset1
= pst
->getOffset(1,
1024 1997, UCAL_OCTOBER
, 26, UCAL_SUNDAY
, (2*60*60*1000), status
);
1025 failure(status
, "getOffset() failed");
1028 int32_t offset2
= cst
->getOffset(1,
1029 1997, UCAL_OCTOBER
, 26, UCAL_SUNDAY
, (2*60*60*1000), 31, status
);
1030 failure(status
, "getOffset() failed");
1032 if(offset1
== offset2
)
1033 errln("FAILURE: Sunday Oct. 26 1997 2:00 has same offset for PST and CST");
1035 // verify error checking
1037 1997, (UCalendarDateFields
)-1, 26, UCAL_SUNDAY
, (2*60*60*1000), status
);
1038 if(U_SUCCESS(status
))
1039 errln("FAILURE: getOffset() succeeded with -1 for month");
1041 status
= U_ZERO_ERROR
;
1042 cst
->setDSTSavings(60*60*1000, status
);
1043 failure(status
, "setDSTSavings() failed");
1045 int32_t savings
= cst
->getDSTSavings();
1046 if(savings
!= 60*60*1000) {
1047 errln("setDSTSavings() failed");
1054 #endif /* #if !UCONFIG_NO_FORMATTING */