3 *******************************************************************************
4 * Copyright (C) 2000-2009, International Business Machines Corporation and *
5 * others. All Rights Reserved. *
6 *******************************************************************************
11 * @bug 4052967 4073209 4073215 4084933 4096952 4109314 4126678 4151406 4151429
12 * @bug 4154525 4154537 4154542 4154650 4159922 4162593 4173604 4176686 4184229 4208960
15 package com.ibm.icu.dev.test.timezone;
16 import com.ibm.icu.util.*;
18 import com.ibm.icu.text.*;
19 import com.ibm.icu.dev.test.*;
20 import java.util.Date;
21 import java.util.Locale;
23 public class TimeZoneRegression extends TestFmwk {
25 public static void main(String[] args) throws Exception {
26 new TimeZoneRegression().run(args);
29 public void Test4052967() {
30 logln("*** CHECK TIMEZONE AGAINST HOST OS SETTING ***");
31 String id = TimeZone.getDefault().getID();
33 // user.timezone is a protected system property
34 logln("user.timezone: " + System.getProperty("user.timezone", "<not set>"));
35 logln("TimeZone.getDefault().getID(): " + id);
36 logln(new Date().toString());
37 logln("*** THE RESULTS OF THIS TEST MUST BE VERIFIED MANUALLY ***");
39 catch (SecurityException e) {
40 warnln("security exception: " + e.toString());
44 public void Test4073209() {
45 TimeZone z1 = TimeZone.getTimeZone("PST");
46 TimeZone z2 = TimeZone.getTimeZone("PST");
47 if (z1 == z2) errln("Fail: TimeZone should return clones");
50 public void Test4073215() {
51 SimpleTimeZone z = new SimpleTimeZone(0, "GMT");
52 if (z.useDaylightTime())
53 errln("Fail: Fix test to start with non-DST zone");
54 z.setStartRule(Calendar.FEBRUARY, 1, Calendar.SUNDAY, 0);
55 z.setEndRule(Calendar.MARCH, -1, Calendar.SUNDAY, 0);
56 if (!z.useDaylightTime())
57 errln("Fail: DST not active");
58 Calendar tempcal = Calendar.getInstance();
60 tempcal.setTimeZone(z);
61 tempcal.set(1997, Calendar.JANUARY, 31);
62 Date d1 = tempcal.getTime();
63 if (z.inDaylightTime(d1)) {
64 errln("Fail: DST not working as expected");
67 tempcal.set(1997, Calendar.MARCH, 1);
68 Date d2 = tempcal.getTime();
69 if (!z.inDaylightTime(d2)) {
70 errln("Fail: DST not working as expected");
73 tempcal.set(1997, Calendar.MARCH, 31);
74 Date d3 = tempcal.getTime();
75 if (z.inDaylightTime(d3)) {
76 errln("Fail: DST not working as expected");
81 * The expected behavior of TimeZone around the boundaries is:
82 * (Assume transition time of 2:00 AM)
83 * day of onset 1:59 AM STD = display name 1:59 AM ST
84 * 2:00 AM STD = display name 3:00 AM DT
85 * day of end 0:59 AM STD = display name 1:59 AM DT
86 * 1:00 AM STD = display name 1:00 AM ST
88 public void Test4084933() {
89 TimeZone tz = TimeZone.getTimeZone("PST");
91 long offset1 = tz.getOffset(1,
92 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (2*60*60*1000));
93 long offset2 = tz.getOffset(1,
94 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (2*60*60*1000)-1);
96 long offset3 = tz.getOffset(1,
97 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (1*60*60*1000));
98 long offset4 = tz.getOffset(1,
99 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (1*60*60*1000)-1);
102 * The following was added just for consistency. It shows that going *to* Daylight
103 * Savings Time (PDT) does work at 2am.
106 long offset5 = tz.getOffset(1,
107 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (2*60*60*1000));
108 long offset6 = tz.getOffset(1,
109 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (2*60*60*1000)-1);
111 long offset7 = tz.getOffset(1,
112 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (1*60*60*1000));
113 long offset8 = tz.getOffset(1,
114 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (1*60*60*1000)-1);
116 long SToffset = -8 * 60*60*1000L;
117 long DToffset = -7 * 60*60*1000L;
118 if (offset1 != SToffset || offset2 != SToffset ||
119 offset3 != SToffset || offset4 != DToffset ||
120 offset5 != DToffset || offset6 != SToffset ||
121 offset7 != SToffset || offset8 != SToffset)
122 warnln("Fail: TimeZone misbehaving");
125 public void Test4096952() {
126 String[] ZONES = { "GMT", "MET", "IST" };
129 for (int i=0; i<ZONES.length; ++i) {
130 TimeZone zone = TimeZone.getTimeZone(ZONES[i]);
131 if (!zone.getID().equals(ZONES[i]))
132 warnln("Fail: Test broken; zones not instantiating");
134 ByteArrayOutputStream baos;
135 ObjectOutputStream ostream =
136 new ObjectOutputStream(baos = new
137 ByteArrayOutputStream());
138 ostream.writeObject(zone);
141 ObjectInputStream istream =
142 new ObjectInputStream(new
143 ByteArrayInputStream(baos.toByteArray()));
144 TimeZone frankenZone = (TimeZone) istream.readObject();
145 //logln("Zone: " + zone);
146 //logln("FrankenZone: " + frankenZone);
147 if (!zone.equals(frankenZone)) {
148 logln("TimeZone " + zone.getID() +
149 " not equal to serialized/deserialized one");
153 if (!pass) errln("Fail: TimeZone serialization/equality bug");
155 catch (IOException e) {
159 catch (ClassNotFoundException e) {
165 public void Test4109314() {
166 GregorianCalendar testCal = (GregorianCalendar)Calendar.getInstance();
167 TimeZone PST = TimeZone.getTimeZone("PST");
168 java.util.Calendar tempcal = java.util.Calendar.getInstance();
170 tempcal.set(1998,Calendar.APRIL,4,22,0);
171 Date d1 = tempcal.getTime();
172 tempcal.set(1998,Calendar.APRIL,5,6,0);
173 Date d2 = tempcal.getTime();
174 tempcal.set(1998,Calendar.OCTOBER,24,22,0);
175 Date d3 = tempcal.getTime();
176 tempcal.set(1998,Calendar.OCTOBER,25,6,0);
177 Date d4 = tempcal.getTime();
178 Object[] testData = {
183 for (int i=0; i<testData.length; i+=3) {
184 testCal.setTimeZone((TimeZone) testData[i]);
185 long t = ((Date)testData[i+1]).getTime();
186 Date end = (Date) testData[i+2];
187 while (t < end.getTime()) {
188 testCal.setTime(new Date(t));
189 if (!checkCalendar314(testCal, (TimeZone) testData[i]))
194 if (!pass) errln("Fail: TZ API inconsistent");
197 boolean checkCalendar314(GregorianCalendar testCal, TimeZone testTZ) {
198 // GregorianCalendar testCal = (GregorianCalendar)aCal.clone();
200 final int ONE_DAY = 24*60*60*1000;
202 int tzOffset, tzRawOffset;
203 Float tzOffsetFloat,tzRawOffsetFloat;
204 // Here is where the user made an error. They were passing in the value of
205 // the MILLSECOND field; you need to pass in the millis in the day in STANDARD
207 int millis = testCal.get(Calendar.MILLISECOND) +
208 1000 * (testCal.get(Calendar.SECOND) +
209 60 * (testCal.get(Calendar.MINUTE) +
210 60 * (testCal.get(Calendar.HOUR_OF_DAY)))) -
211 testCal.get(Calendar.DST_OFFSET);
213 /* Fix up millis to be in range. ASSUME THAT WE ARE NOT AT THE
214 * BEGINNING OR END OF A MONTH. We must add this code because
215 * getOffset() has been changed to be more strict about the parameters
216 * it receives -- it turns out that this test was passing in illegal
218 int date = testCal.get(Calendar.DATE);
219 int dow = testCal.get(Calendar.DAY_OF_WEEK);
223 dow = Calendar.SUNDAY + ((dow - Calendar.SUNDAY + 6) % 7);
225 while (millis >= ONE_DAY) {
228 dow = Calendar.SUNDAY + ((dow - Calendar.SUNDAY + 1) % 7);
231 tzOffset = testTZ.getOffset(testCal.get(Calendar.ERA),
232 testCal.get(Calendar.YEAR),
233 testCal.get(Calendar.MONTH),
237 tzRawOffset = testTZ.getRawOffset();
238 tzOffsetFloat = new Float((float)tzOffset/(float)3600000);
239 tzRawOffsetFloat = new Float((float)tzRawOffset/(float)3600000);
241 Date testDate = testCal.getTime();
243 boolean inDaylightTime = testTZ.inDaylightTime(testDate);
244 SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm");
245 sdf.setCalendar(testCal);
246 String inDaylightTimeString;
252 inDaylightTimeString = " DST ";
253 passed = (tzOffset == (tzRawOffset + 3600000));
257 inDaylightTimeString = " ";
258 passed = (tzOffset == tzRawOffset);
261 String output = testTZ.getID() + " " + sdf.format(testDate) +
262 " Offset(" + tzOffsetFloat + ")" +
263 " RawOffset(" + tzRawOffsetFloat + ")" +
264 " " + millis/(float)3600000 + " " +
265 inDaylightTimeString;
272 if (passed) logln(output); else errln(output);
279 * Yet another _alleged_ bug in TimeZone.getOffset(), a method that never
280 * should have been made public. It's simply too hard to use correctly.
282 * The original test code failed to do the following:
283 * (1) Call Calendar.setTime() before getting the fields!
284 * (2) Use the right millis (as usual) for getOffset(); they were passing
285 * in the MILLIS field, instead of the STANDARD MILLIS IN DAY.
286 * When you fix these two problems, the test passes, as expected.
288 public void Test4126678() {
289 // Note: this test depends on the PST time zone.
290 TimeZone initialZone = TimeZone.getDefault();
291 Calendar cal = Calendar.getInstance();
292 TimeZone tz = TimeZone.getTimeZone("PST");
293 TimeZone.setDefault(tz);
296 java.util.Calendar tempcal = java.util.Calendar.getInstance();
298 tempcal.set(1998, Calendar.APRIL, 5, 10, 0);
299 Date dt = tempcal.getTime();
300 // the dt value is local time in PST.
301 if (!tz.inDaylightTime(dt))
302 errln("We're not in Daylight Savings Time and we should be.\n");
305 int era = cal.get(Calendar.ERA);
306 int year = cal.get(Calendar.YEAR);
307 int month = cal.get(Calendar.MONTH);
308 int day = cal.get(Calendar.DATE);
309 int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
310 int millis = cal.get(Calendar.MILLISECOND) +
311 (cal.get(Calendar.SECOND) +
312 (cal.get(Calendar.MINUTE) +
313 (cal.get(Calendar.HOUR) * 60) * 60) * 1000) -
314 cal.get(Calendar.DST_OFFSET);
316 long offset = tz.getOffset(era, year, month, day, dayOfWeek, millis);
317 long raw_offset = tz.getRawOffset();
318 if (offset == raw_offset)
319 errln("Offsets should not match when in DST");
321 // restore the initial time zone so that this test case
322 // doesn't affect the others.
323 TimeZone.setDefault(initialZone);
327 * TimeZone.getAvailableIDs(int) throws exception for certain values,
328 * due to a faulty constant in TimeZone.java.
330 public void Test4151406() {
332 for (int h=-28; h<=30; ++h) {
333 // h is in half-hours from GMT; rawoffset is in millis
334 int rawoffset = h * 1800000;
335 int hh = (h<0) ? -h : h;
336 String hname = ((h<0) ? "GMT-" : "GMT+") +
337 ((hh/2 < 10) ? "0" : "") +
339 ((hh%2==0) ? "00" : "30");
341 String[] ids = TimeZone.getAvailableIDs(rawoffset);
342 if (ids.length > max) max = ids.length;
343 logln(hname + ' ' + ids.length +
344 ((ids.length > 0) ? (" e.g. " + ids[0]) : ""));
345 } catch (Exception e) {
346 errln(hname + ' ' + "Fail: " + e);
349 logln("Maximum zones per offset = " + max);
352 public void Test4151429() {
354 TimeZone tz = TimeZone.getTimeZone("GMT");
355 /*String name =*/ tz.getDisplayName(true, Integer.MAX_VALUE,
356 Locale.getDefault());
357 errln("IllegalArgumentException not thrown by TimeZone.getDisplayName()");
358 } catch(IllegalArgumentException e) {
359 System.out.print("");
364 * SimpleTimeZone accepts illegal DST savings values. These values
365 * must be non-zero. There is no upper limit at this time.
367 public void Test4154525() {
368 final int GOOD = 1, BAD = 0;
374 Integer.MIN_VALUE, BAD,
375 // Integer.MAX_VALUE, ?, // no upper limit on DST savings at this time
377 for (int i=0; i<DATA.length; i+=2) {
378 int savings = DATA[i];
379 boolean valid = DATA[i+1] == GOOD;
380 String method = null;
381 for (int j=0; j<2; ++j) {
385 method = "constructor";
386 SimpleTimeZone z = new SimpleTimeZone(0, "id",
387 Calendar.JANUARY, 1, 0, 0,
388 Calendar.MARCH, 1, 0, 0,
389 savings); // <- what we're interested in
392 method = "setDSTSavings()";
393 z = new SimpleTimeZone(0, "GMT");
394 z.setDSTSavings(savings);
398 logln("Pass: DST savings of " + savings + " accepted by " + method);
400 errln("Fail: DST savings of " + savings + " accepted by " + method);
402 } catch (IllegalArgumentException e) {
404 errln("Fail: DST savings of " + savings + " to " + method + " gave " + e);
406 logln("Pass: DST savings of " + savings + " to " + method + " gave " + e);
414 * SimpleTimeZone.hasSameRules() doesn't work for zones with no DST
415 * and different DST parameters.
417 public void Test4154537() {
418 // tz1 and tz2 have no DST and different rule parameters
419 SimpleTimeZone tz1 = new SimpleTimeZone(0, "1", 0, 0, 0, 0, 2, 0, 0, 0);
420 SimpleTimeZone tz2 = new SimpleTimeZone(0, "2", 1, 0, 0, 0, 3, 0, 0, 0);
421 // tza and tzA have the same rule params
422 SimpleTimeZone tza = new SimpleTimeZone(0, "a", 0, 1, 0, 0, 3, 2, 0, 0);
423 SimpleTimeZone tzA = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 3, 2, 0, 0);
424 // tzb differs from tza
425 SimpleTimeZone tzb = new SimpleTimeZone(0, "b", 0, 1, 0, 0, 3, 1, 0, 0);
426 if (tz1.useDaylightTime() || tz2.useDaylightTime() ||
427 !tza.useDaylightTime() || !tzA.useDaylightTime() ||
428 !tzb.useDaylightTime()) {
429 errln("Test is broken -- rewrite it");
431 if (!tza.hasSameRules(tzA) || tza.hasSameRules(tzb)) {
432 errln("Fail: hasSameRules() broken for zones with rules");
434 if (!tz1.hasSameRules(tz2)) {
435 errln("Fail: hasSameRules() returns false for zones without rules");
436 errln("zone 1 = " + tz1);
437 errln("zone 2 = " + tz2);
442 * SimpleTimeZone constructors, setStartRule(), and setEndRule() don't
443 * check for out-of-range arguments.
445 public void Test4154542() {
449 final int GOOD_MONTH = Calendar.JANUARY;
450 final int GOOD_DAY = 1;
451 final int GOOD_DAY_OF_WEEK = Calendar.SUNDAY;
452 final int GOOD_TIME = 0;
455 GOOD, Integer.MIN_VALUE, 0, Integer.MAX_VALUE, Integer.MIN_VALUE,
456 GOOD, Calendar.JANUARY, -5, Calendar.SUNDAY, 0,
457 GOOD, Calendar.DECEMBER, 5, Calendar.SATURDAY, 24*60*60*1000-1,
458 BAD, Calendar.DECEMBER, 5, Calendar.SATURDAY, 24*60*60*1000+1,
459 BAD, Calendar.DECEMBER, 5, Calendar.SATURDAY, -1,
460 BAD, Calendar.JANUARY, -6, Calendar.SUNDAY, 0,
461 BAD, Calendar.DECEMBER, 6, Calendar.SATURDAY, 24*60*60*1000,
462 GOOD, Calendar.DECEMBER, 1, 0, 0,
463 GOOD, Calendar.DECEMBER, 31, 0, 0,
464 BAD, Calendar.APRIL, 31, 0, 0,
465 BAD, Calendar.DECEMBER, 32, 0, 0,
466 BAD, Calendar.JANUARY-1, 1, Calendar.SUNDAY, 0,
467 BAD, Calendar.DECEMBER+1, 1, Calendar.SUNDAY, 0,
468 GOOD, Calendar.DECEMBER, 31, -Calendar.SUNDAY, 0,
469 GOOD, Calendar.DECEMBER, 31, -Calendar.SATURDAY, 0,
470 BAD, Calendar.DECEMBER, 32, -Calendar.SATURDAY, 0,
471 BAD, Calendar.DECEMBER, -32, -Calendar.SATURDAY, 0,
472 BAD, Calendar.DECEMBER, 31, -Calendar.SATURDAY-1, 0,
474 SimpleTimeZone zone = new SimpleTimeZone(0, "Z");
475 for (int i=0; i<DATA.length; i+=5) {
476 boolean shouldBeGood = (DATA[i] == GOOD);
477 int month = DATA[i+1];
479 int dayOfWeek = DATA[i+3];
480 int time = DATA[i+4];
484 zone.setStartRule(month, day, dayOfWeek, time);
485 } catch (IllegalArgumentException e) {
488 if ((ex == null) != shouldBeGood) {
489 errln("setStartRule(month=" + month + ", day=" + day +
490 ", dayOfWeek=" + dayOfWeek + ", time=" + time +
491 (shouldBeGood ? (") should work but throws " + ex)
492 : ") should fail but doesn't"));
497 zone.setEndRule(month, day, dayOfWeek, time);
498 } catch (IllegalArgumentException e) {
501 if ((ex == null) != shouldBeGood) {
502 errln("setEndRule(month=" + month + ", day=" + day +
503 ", dayOfWeek=" + dayOfWeek + ", time=" + time +
504 (shouldBeGood ? (") should work but throws " + ex)
505 : ") should fail but doesn't"));
510 /*SimpleTimeZone temp =*/ new SimpleTimeZone(0, "Z",
511 month, day, dayOfWeek, time,
512 GOOD_MONTH, GOOD_DAY, GOOD_DAY_OF_WEEK, GOOD_TIME);
513 } catch (IllegalArgumentException e) {
516 if ((ex == null) != shouldBeGood) {
517 errln("SimpleTimeZone(month=" + month + ", day=" + day +
518 ", dayOfWeek=" + dayOfWeek + ", time=" + time +
519 (shouldBeGood ? (", <end>) should work but throws " + ex)
520 : ", <end>) should fail but doesn't"));
525 /*SimpleTimeZone temp = */new SimpleTimeZone(0, "Z",
526 GOOD_MONTH, GOOD_DAY, GOOD_DAY_OF_WEEK, GOOD_TIME,
527 month, day, dayOfWeek, time);
529 } catch (IllegalArgumentException e) {
532 if ((ex == null) != shouldBeGood) {
533 errln("SimpleTimeZone(<start>, month=" + month + ", day=" + day +
534 ", dayOfWeek=" + dayOfWeek + ", time=" + time +
535 (shouldBeGood ? (") should work but throws " + ex)
536 : ") should fail but doesn't"));
542 * SimpleTimeZone.getOffset accepts illegal arguments.
544 public void Test4154650() {
545 final int GOOD=1, BAD=0;
546 final int GOOD_ERA=GregorianCalendar.AD, GOOD_YEAR=1998, GOOD_MONTH=Calendar.AUGUST;
547 final int GOOD_DAY=2, GOOD_DOW=Calendar.SUNDAY, GOOD_TIME=16*3600000;
549 GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
551 GOOD, GregorianCalendar.BC, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
552 GOOD, GregorianCalendar.AD, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
553 BAD, GregorianCalendar.BC-1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
554 BAD, GregorianCalendar.AD+1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
556 GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, GOOD_DAY, GOOD_DOW, GOOD_TIME,
557 GOOD, GOOD_ERA, GOOD_YEAR, Calendar.DECEMBER, GOOD_DAY, GOOD_DOW, GOOD_TIME,
558 BAD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY-1, GOOD_DAY, GOOD_DOW, GOOD_TIME,
559 BAD, GOOD_ERA, GOOD_YEAR, Calendar.DECEMBER+1, GOOD_DAY, GOOD_DOW, GOOD_TIME,
561 GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 1, GOOD_DOW, GOOD_TIME,
562 GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 31, GOOD_DOW, GOOD_TIME,
563 BAD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 0, GOOD_DOW, GOOD_TIME,
564 BAD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 32, GOOD_DOW, GOOD_TIME,
566 GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SUNDAY, GOOD_TIME,
567 GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SATURDAY, GOOD_TIME,
568 BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SUNDAY-1, GOOD_TIME,
569 BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SATURDAY+1, GOOD_TIME,
571 GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 0,
572 GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000-1,
573 BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, -1,
574 BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000,
577 TimeZone tz = TimeZone.getDefault();
578 for (int i=0; i<DATA.length; i+=7) {
579 boolean good = DATA[i] == GOOD;
580 IllegalArgumentException e = null;
582 /*int offset =*/ tz.getOffset(DATA[i+1], DATA[i+2], DATA[i+3],
583 DATA[i+4], DATA[i+5], DATA[i+6]);
585 } catch (IllegalArgumentException ex) {
588 if (good != (e == null)) {
589 errln("Fail: getOffset(" +
590 DATA[i+1] + ", " + DATA[i+2] + ", " + DATA[i+3] + ", " +
591 DATA[i+4] + ", " + DATA[i+5] + ", " + DATA[i+6] +
592 (good ? (") threw " + e) : ") accepts invalid args"));
598 * TimeZone constructors allow null IDs.
600 public void Test4159922() {
603 // TimeZone API. Only hasSameRules() and setDefault() should
606 z = TimeZone.getTimeZone(null);
607 errln("FAIL: Null allowed in getTimeZone");
608 } catch (NullPointerException e) {
609 System.out.print("");
611 z = TimeZone.getTimeZone("GMT");
613 // {dlf} requiring cast for disambiguation is ok for compatibility since null
614 // is not a valid argument to this API
615 z.getDisplayName(false, TimeZone.SHORT, (ULocale)null);
616 errln("FAIL: Null allowed in getDisplayName(3)");
617 } catch (NullPointerException e) {
618 System.out.print("");
622 z.getDisplayName((ULocale)null);
623 errln("FAIL: Null allowed in getDisplayName(1)");
624 } catch (NullPointerException e) {
625 System.out.print("");
628 if (z.hasSameRules(null)) {
629 errln("FAIL: hasSameRules returned true");
631 } catch (NullPointerException e) {
632 errln("FAIL: Null NOT allowed in hasSameRules");
635 z.inDaylightTime(null);
636 errln("FAIL: Null allowed in inDaylightTime");
637 } catch (NullPointerException e) {
638 System.out.print("");
642 errln("FAIL: Null allowed in setID");
643 } catch (NullPointerException e) {
644 System.out.print("");
647 TimeZone save = TimeZone.getDefault();
649 TimeZone.setDefault(null);
650 } catch (NullPointerException e) {
651 errln("FAIL: Null NOT allowed in setDefault");
653 TimeZone.setDefault(save);
656 // SimpleTimeZone API
657 SimpleTimeZone s = null;
659 s = new SimpleTimeZone(0, null);
660 errln("FAIL: Null allowed in SimpleTimeZone(2)");
661 } catch (NullPointerException e) {
662 System.out.print("");
665 s = new SimpleTimeZone(0, null, 0, 1, 0, 0, 0, 1, 0, 0);
666 errln("FAIL: Null allowed in SimpleTimeZone(10)");
667 } catch (NullPointerException e) {
668 System.out.print("");
671 s = new SimpleTimeZone(0, null, 0, 1, 0, 0, 0, 1, 0, 0, 1000);
672 errln("FAIL: Null allowed in SimpleTimeZone(11)");
673 } catch (NullPointerException e) {
674 System.out.print("");
677 errln("FAIL: Did not get the expected Exception");
682 * TimeZone broken at midnight. The TimeZone code fails to handle
683 * transitions at midnight correctly.
685 public void Test4162593() {
686 SimpleDateFormat fmt = new SimpleDateFormat("z", Locale.US);
687 final int ONE_HOUR = 60*60*1000;
688 final float H = (float) ONE_HOUR;
689 TimeZone initialZone = TimeZone.getDefault();
690 SimpleDateFormat sdf = new SimpleDateFormat("MMM dd yyyy HH:mm z");
692 SimpleTimeZone asuncion = new SimpleTimeZone(-4*ONE_HOUR, "America/Asuncion" /*PY%sT*/,
693 Calendar.OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR,
694 Calendar.MARCH, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR);
698 * Transition expected between start+1H and start+2H
701 new SimpleTimeZone(2*ONE_HOUR, "Asia/Damascus" /*EE%sT*/,
702 Calendar.APRIL, 1, 0 /*DOM*/, 0*ONE_HOUR,
703 Calendar.OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR),
704 new int[] {1998, Calendar.SEPTEMBER, 30, 22, 0},
708 new int[] {2000, Calendar.FEBRUARY, 28, 22, 0},
712 new int[] {2000, Calendar.FEBRUARY, 29, 22, 0},
716 String[] zone = new String[4];
718 for (int j=0; j<DATA.length; j+=3) {
719 TimeZone tz = (TimeZone)DATA[j];
720 TimeZone.setDefault(tz);
724 // Must construct the Date object AFTER setting the default zone
725 int[] p = (int[])DATA[j+1];
726 Calendar cal = Calendar.getInstance();
728 cal.set(p[0], p[1], p[2], p[3], p[4]);
729 long start = cal.getTime().getTime();
730 boolean transitionExpected = ((Boolean)DATA[j+2]).booleanValue();
732 logln(tz.getID() + ":");
733 for (int i=0; i<4; ++i) {
734 Date d = new Date(start + i*ONE_HOUR);
735 zone[i] = fmt.format(d);
736 logln("" + i + ": " + sdf.format(d) + " => " + zone[i] +
737 " (" + d.getTime()/H + ")");
739 cal.set(p[0], p[1], p[2], 0, 0);
740 for (int i=0; i<4; ++i) {
742 int dom = p[2]+(h>=24?1:0);
746 cal.set(p[0], p[1], dom, 0, 0);
747 int off = tz.getOffset(GregorianCalendar.AD,
748 cal.get(Calendar.YEAR),
749 cal.get(Calendar.MONTH),
750 cal.get(Calendar.DATE),
751 cal.get(Calendar.DAY_OF_WEEK),
753 cal.add(Calendar.HOUR, h);
754 int dstOffset = cal.get(Calendar.DST_OFFSET);
755 logln("h=" + h + "; dom=" + dom +
756 "; ZONE_OFFSET=" + cal.get(Calendar.ZONE_OFFSET)/H +
757 "; DST_OFFSET=" + dstOffset/H +
758 "; getOffset()=" + off/H +
759 " (" + cal.getTime().getTime()/H + ")");
761 if (zone[0].equals(zone[1]) &&
762 (zone[1].equals(zone[2]) != transitionExpected) &&
763 zone[2].equals(zone[3])) {
764 logln("Ok: transition " + transitionExpected);
766 errln("FAIL: expected " +
767 (transitionExpected?"transition":"no transition"));
771 // restore the initial time zone so that this test case
772 // doesn't affect the others.
773 TimeZone.setDefault(initialZone);
777 * TimeZone broken in last hour of year
779 public void Test4173604() {
780 TimeZone pst = TimeZone.getTimeZone("PST");
781 int o22 = pst.getOffset(1, 1998, 11, 31, Calendar.THURSDAY, 22*60*60*1000);
782 int o23 = pst.getOffset(1, 1998, 11, 31, Calendar.THURSDAY, 23*60*60*1000);
783 int o00 = pst.getOffset(1, 1999, 0, 1, Calendar.FRIDAY, 0);
784 if (o22 != o23 || o22 != o00) {
785 errln("Offsets should be the same (for PST), but got: " +
786 "12/31 22:00 " + o22 +
787 ", 12/31 23:00 " + o23 +
788 ", 01/01 00:00 " + o00);
791 GregorianCalendar cal = new GregorianCalendar();
792 cal.setTimeZone(pst);
794 cal.set(1998, Calendar.JANUARY, 1);
795 int lastDST = cal.get(Calendar.DST_OFFSET);
798 while (cal.get(Calendar.YEAR) < 2000) {
799 cal.add(Calendar.MINUTE, delta);
800 if (cal.get(Calendar.DST_OFFSET) != lastDST) {
802 Calendar t = (Calendar)cal.clone();
803 t.add(Calendar.MINUTE, -delta);
804 logln(t.getTime() + " " + t.get(Calendar.DST_OFFSET));
805 logln(cal.getTime() + " " + (lastDST=cal.get(Calendar.DST_OFFSET)));
808 if (transitions != 4) {
809 errln("Saw " + transitions + " transitions; should have seen 4");
814 * getDisplayName doesn't work with unusual savings/offsets.
816 public void Test4176686() {
817 // Construct a zone that does not observe DST but
818 // that does have a DST savings (which should be ignored).
819 int offset = 90 * 60000; // 1:30
820 SimpleTimeZone z1 = new SimpleTimeZone(offset, "_std_zone_");
821 z1.setDSTSavings(45 * 60000); // 0:45
823 // Construct a zone that observes DST for the first 6 months.
824 SimpleTimeZone z2 = new SimpleTimeZone(offset, "_dst_zone_");
825 z2.setDSTSavings(45 * 60000); // 0:45
826 z2.setStartRule(Calendar.JANUARY, 1, 0);
827 z2.setEndRule(Calendar.JULY, 1, 0);
829 // Also check DateFormat
830 DateFormat fmt1 = new SimpleDateFormat("z");
831 fmt1.setTimeZone(z1); // Format uses standard zone
832 DateFormat fmt2 = new SimpleDateFormat("z");
833 fmt2.setTimeZone(z2); // Format uses DST zone
834 java.util.Calendar tempcal = java.util.Calendar.getInstance();
836 tempcal.set(1970, Calendar.FEBRUARY, 1);
837 Date dst = tempcal.getTime(); // Time in DST
838 tempcal.set(1970, Calendar.AUGUST, 1);
839 Date std = tempcal.getTime(); // Time in standard
841 // Description, Result, Expected Result
843 "getDisplayName(false, SHORT)/std zone",
844 z1.getDisplayName(false, TimeZone.SHORT), "GMT+01:30",
845 "getDisplayName(false, LONG)/std zone",
846 z1.getDisplayName(false, TimeZone.LONG ), "GMT+01:30",
847 "getDisplayName(true, SHORT)/std zone",
848 z1.getDisplayName(true, TimeZone.SHORT), "GMT+01:30",
849 "getDisplayName(true, LONG)/std zone",
850 z1.getDisplayName(true, TimeZone.LONG ), "GMT+01:30",
851 "getDisplayName(false, SHORT)/dst zone",
852 z2.getDisplayName(false, TimeZone.SHORT), "GMT+01:30",
853 "getDisplayName(false, LONG)/dst zone",
854 z2.getDisplayName(false, TimeZone.LONG ), "GMT+01:30",
855 "getDisplayName(true, SHORT)/dst zone",
856 z2.getDisplayName(true, TimeZone.SHORT), "GMT+02:15",
857 "getDisplayName(true, LONG)/dst zone",
858 z2.getDisplayName(true, TimeZone.LONG ), "GMT+02:15",
859 "DateFormat.format(std)/std zone", fmt1.format(std), "GMT+01:30",
860 "DateFormat.format(dst)/std zone", fmt1.format(dst), "GMT+01:30",
861 "DateFormat.format(std)/dst zone", fmt2.format(std), "GMT+01:30",
862 "DateFormat.format(dst)/dst zone", fmt2.format(dst), "GMT+02:15",
865 for (int i=0; i<DATA.length; i+=3) {
866 if (!DATA[i+1].equals(DATA[i+2])) {
867 errln("FAIL: " + DATA[i] + " -> " + DATA[i+1] + ", exp " + DATA[i+2]);
873 * SimpleTimeZone allows invalid DOM values.
875 // Current orgnaization of data in zoneinfor.res allows negative
876 // values from DOM so comment these tests out
878 public void Test4184229() {
879 SimpleTimeZone zone = null;
881 zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0);
882 errln("Failed. No exception has been thrown for DOM -1 startDay");
883 } catch(IllegalArgumentException e) {
884 logln("(a) " + e.getMessage());
887 zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0);
888 errln("Failed. No exception has been thrown for DOM -1 endDay");
889 } catch(IllegalArgumentException e) {
890 logln("(b) " + e.getMessage());
893 zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0, 1000);
894 errln("Failed. No exception has been thrown for DOM -1 startDay +savings");
895 } catch(IllegalArgumentException e) {
896 logln("(c) " + e.getMessage());
899 zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0, 1000);
900 errln("Failed. No exception has been thrown for DOM -1 endDay +savings");
901 } catch(IllegalArgumentException e) {
902 logln("(d) " + e.getMessage());
904 // Make a valid constructor call for subsequent tests.
906 zone = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 0, 1, 0, 0);
909 zone.setStartRule(0, -1, 0, 0);
910 errln("Failed. No exception has been thrown for DOM -1 setStartRule +savings");
911 } catch(IllegalArgumentException e) {
912 logln("(e) " + e.getMessage());
915 zone.setStartRule(0, -1, 0);
916 errln("Failed. No exception has been thrown for DOM -1 setStartRule");
917 } catch(IllegalArgumentException e) {
918 logln("(f) " + e.getMessage());
921 zone.setEndRule(0, -1, 0, 0);
922 errln("Failed. No exception has been thrown for DOM -1 setEndRule +savings");
923 } catch(IllegalArgumentException e) {
924 logln("(g) " + e.getMessage());
927 zone.setEndRule(0, -1, 0);
928 errln("Failed. No exception has been thrown for DOM -1 setEndRule");
929 } catch(IllegalArgumentException e) {
930 logln("(h) " + e.getMessage());
936 * SimpleTimeZone.getOffset() throws IllegalArgumentException when to get
937 * of 2/29/1996 (leap day).
939 public void Test4208960 () {
940 TimeZone tz = TimeZone.getTimeZone("PST");
942 /*int offset =*/ tz.getOffset(GregorianCalendar.AD, 1996, Calendar.FEBRUARY, 29,
943 Calendar.THURSDAY, 0);
945 } catch (IllegalArgumentException e) {
946 errln("FAILED: to get TimeZone.getOffset(2/29/96)");
949 /*int offset =*/ tz.getOffset(GregorianCalendar.AD, 1997, Calendar.FEBRUARY, 29,
950 Calendar.THURSDAY, 0);
952 warnln("FAILED: TimeZone.getOffset(2/29/97) expected to throw Exception.");
953 } catch (IllegalArgumentException e) {
954 logln("got IllegalArgumentException");
959 * Test to see if DateFormat understands zone equivalency groups. It
960 * might seem that this should be a DateFormat test, but it's really a
961 * TimeZone test -- the changes to DateFormat are minor.
963 * We use two known, zones that are equivalent, where one zone has
964 * localized name data, and the other doesn't, in some locale.
966 public void TestJ449() {
967 // not used String str;
969 // Modify the following three as necessary. The two IDs must
970 // specify two zones in the same equivalency group. One must have
971 // locale data in 'loc'; the other must not.
972 String idWithLocaleData = "America/Los_Angeles";
973 String idWithoutLocaleData = "PST"; // "US/Pacific";
974 Locale loc = new Locale("en", "", "");
976 TimeZone zoneWith = TimeZone.getTimeZone(idWithLocaleData);
977 TimeZone zoneWithout = TimeZone.getTimeZone(idWithoutLocaleData);
978 // Make sure we got valid zones
979 if (!(zoneWith.getID().equals(idWithLocaleData) &&
980 zoneWithout.getID().equals(idWithoutLocaleData))) {
981 warnln("Fail: Unable to create zones");
983 GregorianCalendar calWith = new GregorianCalendar(zoneWith);
984 GregorianCalendar calWithout = new GregorianCalendar(zoneWithout);
985 SimpleDateFormat fmt =
986 new SimpleDateFormat("MMM d yyyy hh:mm a zzz", loc);
987 Date date = new Date(0L);
988 fmt.setCalendar(calWith);
989 String strWith = fmt.format(date);
990 fmt.setCalendar(calWithout);
991 String strWithout = fmt.format(date);
992 if (strWith.equals(strWithout)) {
993 logln("Ok: " + idWithLocaleData + " -> " +
994 strWith + "; " + idWithoutLocaleData + " -> " +
997 errln("FAIL: " + idWithLocaleData + " -> " +
998 strWith + "; " + idWithoutLocaleData + " -> " +
1005 * getOffset returns wrong offset for days in early 20th century
1007 public void TestJ5134() {
1008 GregorianCalendar testCal = (GregorianCalendar)Calendar.getInstance();
1009 TimeZone icuEastern = TimeZone.getTimeZone("America/New_York");
1010 testCal.setTimeZone(icuEastern);
1011 testCal.set(1900, Calendar.JANUARY, 1, 0, 0, 0);
1012 long time = testCal.getTimeInMillis();
1014 int offset = icuEastern.getOffset(time);
1015 if (offset != -18000000) {
1016 errln("FAIL: UTC offset in time zone America/New_York on Jan 1, 1900 -> " + offset);
1018 boolean isDst = icuEastern.inDaylightTime(new Date(time));
1020 errln("FAIL: DST is observed in time zone America/New_York on Jan 1, 1900");
1023 //#if defined(FOUNDATION10) || defined(J2SE13)
1025 if (System.getProperty("java.vendor", "").startsWith("IBM") &&
1026 System.getProperty("java.version", "").equals("1.4.1")) {
1027 // IBM JDK 1.4.1 has a bug and fails to run this test case.
1030 java.util.TimeZone jdkEastern = java.util.TimeZone.getTimeZone("America/New_York");
1031 // Compare offset and DST observation with JDK and ICU for 50 years since 1900
1032 testCal.add(Calendar.YEAR, 50);
1033 long endTime = testCal.getTimeInMillis();
1036 while (time < endTime) {
1037 offset = icuEastern.getOffset(time);
1038 jdkOffset = jdkEastern.getOffset(time);
1039 if (offset != jdkOffset) {
1040 errln("FAIL: Incompatible UTC offset -> JDK:" + jdkOffset + "/ICU:" + offset + " [" + time + "]");
1042 Date d = new Date(time);
1043 isDst = icuEastern.inDaylightTime(d);
1044 isDstJdk = jdkEastern.inDaylightTime(d);
1045 if (isDst != isDstJdk) {
1046 errln("FAIL: Incompatible DST -> JDK:" + isDstJdk + "/ICU:" + isDst + " [" + time + "]");
1048 time += 24*60*60*1000L; // increment 1 day
1054 * Test setRawOffset works OK with system timezone
1056 public void TestT5280() {
1057 String[] tzids = TimeZone.getAvailableIDs();
1058 for (int i = 0; i < tzids.length; i++) {
1059 TimeZone tz = TimeZone.getTimeZone(tzids[i]);
1060 boolean useDst = tz.useDaylightTime();
1062 // Increase offset for 30 minutes
1063 int newRawOffset = tz.getRawOffset() + 30*60*1000;
1065 tz.setRawOffset(newRawOffset);
1066 } catch (Exception e) {
1067 errln("FAIL: setRawOffset throws an exception");
1069 int offset = tz.getRawOffset();
1070 if (offset != newRawOffset) {
1071 errln("FAIL: Modified zone(" + tz.getID() + ") - getRawOffset returns " + offset + "/ Expected: " + newRawOffset);
1074 // Check if DST observation status is not unexpectedly changed.
1075 boolean newDst = tz.useDaylightTime();
1076 if (useDst != newDst) {
1077 errln("FAIL: Modified zone(" + tz.getID() + ") - useDaylightTime has changed from " + useDst + " to " + newDst);
1079 // Make sure the offset is preserved in a clone
1080 TimeZone tzClone = (TimeZone)tz.clone();
1081 offset = tzClone.getRawOffset();
1082 if (offset != newRawOffset) {
1083 errln("FAIL: Cloned modified zone(" + tz.getID() + ") - getRawOffset returns " + offset + "/ Expected: " + newRawOffset);
1089 * Zone ID is not set by a SimpleTimeZone constructor
1091 public void TestT5432() {
1092 String tzid = "MyZone";
1095 // 2-arg constructor
1096 stz = new SimpleTimeZone(0, tzid);
1097 if (!tzid.equals(stz.getID())) {
1098 errln("FAIL: Bad zone id (" + stz.getID() + ") is returned - expected ("
1099 + tzid + ") [2-arg constructor]");
1102 // 10-arg constructor
1103 stz = new SimpleTimeZone(0, tzid, 3, -1, 1, 3600000, 9, -1, 1, 3600000);
1104 if (!tzid.equals(stz.getID())) {
1105 errln("FAIL: Bad zone id (" + stz.getID() + ") is returned - expected ("
1106 + tzid + ") [10-arg constructor]");
1109 // 11-arg constructor
1110 stz = new SimpleTimeZone(0, tzid, 3, -1, 1, 3600000, 9, -1, 1, 3600000, 3600000);
1111 if (!tzid.equals(stz.getID())) {
1112 errln("FAIL: Bad zone id (" + stz.getID() + ") is returned - expected ("
1113 + tzid + ") [11-arg constructor]");
1116 // 13-arg constructor - this version had a problem reported by trac#5432
1117 stz = new SimpleTimeZone(0, tzid, 3, -1, 1, 3600000, SimpleTimeZone.WALL_TIME,
1118 9, -1, 1, 3600000, SimpleTimeZone.WALL_TIME, 3600000);
1119 if (!tzid.equals(stz.getID())) {
1120 errln("FAIL: Bad zone id (" + stz.getID() + ") is returned - expected ("
1121 + tzid + ") [13-arg constructor]");
1126 public void TestJohannesburg() {
1127 String j_id="Africa/Johannesburg";
1128 TimeZone johannesburg = TimeZone.getTimeZone(j_id);
1129 final int ONE_HOUR = 60*60*1000;
1130 int expectedOffset = ONE_HOUR*2; // GMT+2 - NO DST
1131 int offset = johannesburg.getOffset(GregorianCalendar.AD,2007,Calendar.JULY,5,Calendar.THURSDAY,0);
1133 if(offset != expectedOffset) {
1134 errln("FAIL: zone " + j_id +" returned offset in July " + offset +", expected "+expectedOffset);
1136 logln("OK: zone " + j_id +" returned offset in July: " + offset);
1139 int offset2 = johannesburg.getOffset(GregorianCalendar.AD,2007,Calendar.DECEMBER,12,Calendar.WEDNESDAY,0);
1141 if(offset2 != expectedOffset) {
1142 errln("FAIL: zone " + j_id +" returned offset in December " + offset2 +", expected "+expectedOffset);
1144 logln("OK: zone " + j_id +" returned offset in December: " + offset2);