]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-52_1/main/tests/core/src/com/ibm/icu/dev/test/timezone/TimeZoneRegression.java
Upgrade ICU4J.
[Dictionary.git] / jars / icu4j-52_1 / main / tests / core / src / com / ibm / icu / dev / test / timezone / TimeZoneRegression.java
1 /**
2  *******************************************************************************
3  * Copyright (C) 2000-2013, International Business Machines Corporation and    *
4  * others. All Rights Reserved.                                                *
5  *******************************************************************************
6  */
7
8 /**
9  * @test 1.18 99/09/21
10  * @bug 4052967 4073209 4073215 4084933 4096952 4109314 4126678 4151406 4151429
11  * @bug 4154525 4154537 4154542 4154650 4159922 4162593 4173604 4176686 4184229 4208960
12  */
13
14 package com.ibm.icu.dev.test.timezone;
15 import java.io.ByteArrayInputStream;
16 import java.io.ByteArrayOutputStream;
17 import java.io.IOException;
18 import java.io.ObjectInputStream;
19 import java.io.ObjectOutputStream;
20 import java.security.AccessControlException;
21 import java.util.Date;
22 import java.util.Locale;
23
24 import com.ibm.icu.dev.test.TestFmwk;
25 import com.ibm.icu.text.DateFormat;
26 import com.ibm.icu.text.SimpleDateFormat;
27 import com.ibm.icu.util.Calendar;
28 import com.ibm.icu.util.GregorianCalendar;
29 import com.ibm.icu.util.SimpleTimeZone;
30 import com.ibm.icu.util.TimeZone;
31 import com.ibm.icu.util.ULocale;
32
33 public class TimeZoneRegression extends TestFmwk {
34
35     public static void main(String[] args) throws Exception {
36         new TimeZoneRegression().run(args);
37     }
38
39     public void Test4052967() {
40         logln("*** CHECK TIMEZONE AGAINST HOST OS SETTING ***");
41         String id = TimeZone.getDefault().getID();
42         try {
43             try {
44                 logln("user.timezone: " + System.getProperty("user.timezone", "<not set>"));
45             } catch (AccessControlException e) {
46                 // user.timezone is a protected system property - ignore
47             }
48             logln("TimeZone.getDefault().getID(): " + id);
49             logln(new Date().toString());
50             logln("*** THE RESULTS OF THIS TEST MUST BE VERIFIED MANUALLY ***");
51         }
52         catch (SecurityException e) {
53             warnln("security exception: " + e.toString());
54         }
55     }
56
57     public void Test4073209() {
58         TimeZone z1 = TimeZone.getTimeZone("PST");
59         TimeZone z2 = TimeZone.getTimeZone("PST");
60         if (z1 == z2) errln("Fail: TimeZone should return clones");
61     }
62
63     public void Test4073215() {
64         SimpleTimeZone z = new SimpleTimeZone(0, "GMT");
65         if (z.useDaylightTime())
66             errln("Fail: Fix test to start with non-DST zone");
67         z.setStartRule(Calendar.FEBRUARY, 1, Calendar.SUNDAY, 0);
68         z.setEndRule(Calendar.MARCH, -1, Calendar.SUNDAY, 0);
69         if (!z.useDaylightTime())
70             errln("Fail: DST not active");
71         Calendar tempcal = Calendar.getInstance();
72         tempcal.clear();
73         tempcal.setTimeZone(z);
74         tempcal.set(1997, Calendar.JANUARY, 31);
75         Date d1 = tempcal.getTime();
76         if (z.inDaylightTime(d1)) {
77             errln("Fail: DST not working as expected");
78         } 
79
80         tempcal.set(1997, Calendar.MARCH, 1);
81         Date d2 = tempcal.getTime();
82         if (!z.inDaylightTime(d2)) {
83             errln("Fail: DST not working as expected");
84         }
85         tempcal.clear();
86         tempcal.set(1997, Calendar.MARCH, 31);
87         Date d3 = tempcal.getTime();
88         if (z.inDaylightTime(d3)) {
89             errln("Fail: DST not working as expected");
90         } 
91     }
92
93     /**
94      * The expected behavior of TimeZone around the boundaries is:
95      * (Assume transition time of 2:00 AM)
96      *    day of onset 1:59 AM STD  = display name 1:59 AM ST
97      *                 2:00 AM STD  = display name 3:00 AM DT
98      *    day of end   0:59 AM STD  = display name 1:59 AM DT
99      *                 1:00 AM STD  = display name 1:00 AM ST
100      */
101     public void Test4084933() {
102         TimeZone tz = TimeZone.getTimeZone("PST");
103
104         long offset1 = tz.getOffset(1,
105             1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (2*60*60*1000));
106         long offset2 = tz.getOffset(1,
107             1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (2*60*60*1000)-1);
108
109         long offset3 = tz.getOffset(1,
110             1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (1*60*60*1000));
111         long offset4 = tz.getOffset(1,
112             1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (1*60*60*1000)-1);
113
114         /*
115          *  The following was added just for consistency.  It shows that going *to* Daylight
116          *  Savings Time (PDT) does work at 2am.
117          */
118
119         long offset5 = tz.getOffset(1,
120             1997, Calendar.APRIL, 6, Calendar.SUNDAY, (2*60*60*1000));
121         long offset6 = tz.getOffset(1,
122             1997, Calendar.APRIL, 6, Calendar.SUNDAY, (2*60*60*1000)-1);
123
124         long offset7 = tz.getOffset(1,
125             1997, Calendar.APRIL, 6, Calendar.SUNDAY, (1*60*60*1000));
126         long offset8 = tz.getOffset(1,
127             1997, Calendar.APRIL, 6, Calendar.SUNDAY, (1*60*60*1000)-1);
128
129         long SToffset = -8 * 60*60*1000L;
130         long DToffset = -7 * 60*60*1000L;
131         if (offset1 != SToffset || offset2 != SToffset ||
132             offset3 != SToffset || offset4 != DToffset ||
133             offset5 != DToffset || offset6 != SToffset ||
134             offset7 != SToffset || offset8 != SToffset)
135             warnln("Fail: TimeZone misbehaving");
136     }
137
138     public void Test4096952() {
139         String[] ZONES = { "GMT", "MET", "IST" };
140         boolean pass = true;
141         try {
142             for (int i=0; i<ZONES.length; ++i) {
143                 TimeZone zone = TimeZone.getTimeZone(ZONES[i]);
144                 if (!zone.getID().equals(ZONES[i]))
145                     warnln("Fail: Test broken; zones not instantiating");
146
147                 ByteArrayOutputStream baos;
148                 ObjectOutputStream ostream =
149                     new ObjectOutputStream(baos = new
150                                            ByteArrayOutputStream());
151                 ostream.writeObject(zone);
152                 ostream.close();
153                 baos.close();
154                 ObjectInputStream istream =
155                     new ObjectInputStream(new
156                                           ByteArrayInputStream(baos.toByteArray()));
157                 TimeZone frankenZone = (TimeZone) istream.readObject();
158                 //logln("Zone:        " + zone);
159                 //logln("FrankenZone: " + frankenZone);
160                 if (!zone.equals(frankenZone)) {
161                     logln("TimeZone " + zone.getID() +
162                           " not equal to serialized/deserialized one");
163                     pass = false;
164                 }
165             }
166             if (!pass) errln("Fail: TimeZone serialization/equality bug");
167         }
168         catch (IOException e) {
169             errln("Fail: " + e);
170             e.printStackTrace();
171         }
172         catch (ClassNotFoundException e) {
173             errln("Fail: " + e);
174             e.printStackTrace();
175         }
176     }
177
178     public void Test4109314() {
179         GregorianCalendar testCal = (GregorianCalendar)Calendar.getInstance();
180         TimeZone PST = TimeZone.getTimeZone("PST");
181         java.util.Calendar tempcal = java.util.Calendar.getInstance();
182         tempcal.clear();
183         tempcal.set(1998,Calendar.APRIL,4,22,0);
184         Date d1 = tempcal.getTime();
185         tempcal.set(1998,Calendar.APRIL,5,6,0);
186         Date d2 = tempcal.getTime();
187         tempcal.set(1998,Calendar.OCTOBER,24,22,0);
188         Date d3 = tempcal.getTime();
189         tempcal.set(1998,Calendar.OCTOBER,25,6,0);
190         Date d4 = tempcal.getTime();
191         Object[] testData = {
192             PST, d1, d2,
193             PST, d3, d4,
194         };
195         boolean pass=true;
196         for (int i=0; i<testData.length; i+=3) {
197             testCal.setTimeZone((TimeZone) testData[i]);
198             long t = ((Date)testData[i+1]).getTime();
199             Date end = (Date) testData[i+2];
200             while (t < end.getTime()) {
201                 testCal.setTime(new Date(t));
202                 if (!checkCalendar314(testCal, (TimeZone) testData[i]))
203                     pass = false;
204                 t += 60*60*1000L;
205             }
206         }
207         if (!pass) errln("Fail: TZ API inconsistent");
208     }
209
210     boolean checkCalendar314(GregorianCalendar testCal, TimeZone testTZ) {
211         // GregorianCalendar testCal = (GregorianCalendar)aCal.clone();
212
213         final int ONE_DAY = 24*60*60*1000;
214
215         int tzOffset, tzRawOffset;
216         Float tzOffsetFloat,tzRawOffsetFloat;
217         // Here is where the user made an error.  They were passing in the value of
218         // the MILLSECOND field; you need to pass in the millis in the day in STANDARD
219         // time.
220         int millis = testCal.get(Calendar.MILLISECOND) +
221             1000 * (testCal.get(Calendar.SECOND) +
222                     60 * (testCal.get(Calendar.MINUTE) +
223                           60 * (testCal.get(Calendar.HOUR_OF_DAY)))) -
224             testCal.get(Calendar.DST_OFFSET);
225
226         /* Fix up millis to be in range.  ASSUME THAT WE ARE NOT AT THE
227          * BEGINNING OR END OF A MONTH.  We must add this code because
228          * getOffset() has been changed to be more strict about the parameters
229          * it receives -- it turns out that this test was passing in illegal
230          * values. */
231         int date = testCal.get(Calendar.DATE);
232         int dow  = testCal.get(Calendar.DAY_OF_WEEK);
233         while (millis < 0) {
234             millis += ONE_DAY;
235             --date;
236             dow = Calendar.SUNDAY + ((dow - Calendar.SUNDAY + 6) % 7);
237         }
238         while (millis >= ONE_DAY) {
239             millis -= ONE_DAY;
240             ++date;
241             dow = Calendar.SUNDAY + ((dow - Calendar.SUNDAY + 1) % 7);
242         }
243
244         tzOffset = testTZ.getOffset(testCal.get(Calendar.ERA),
245                                     testCal.get(Calendar.YEAR),
246                                     testCal.get(Calendar.MONTH),
247                                     date,
248                                     dow,
249                                     millis);
250         tzRawOffset = testTZ.getRawOffset();
251         tzOffsetFloat = new Float((float)tzOffset/(float)3600000);
252         tzRawOffsetFloat = new Float((float)tzRawOffset/(float)3600000);
253
254         Date testDate = testCal.getTime();
255
256         boolean inDaylightTime = testTZ.inDaylightTime(testDate);
257         SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm");
258         sdf.setCalendar(testCal);
259         String inDaylightTimeString;
260
261         boolean passed;
262
263         if (inDaylightTime)
264         {
265             inDaylightTimeString = " DST ";
266             passed = (tzOffset == (tzRawOffset + 3600000));
267         }
268         else
269         {
270             inDaylightTimeString = "     ";
271             passed = (tzOffset == tzRawOffset);
272         }
273
274         String output = testTZ.getID() + " " + sdf.format(testDate) +
275             " Offset(" + tzOffsetFloat + ")" +
276             " RawOffset(" + tzRawOffsetFloat + ")" +
277             " " + millis/(float)3600000 + " " +
278             inDaylightTimeString;
279
280         if (passed)
281             output += "     ";
282         else
283             output += "ERROR";
284
285         if (passed) logln(output); else errln(output);
286         return passed;
287     }
288
289     /**
290      * CANNOT REPRODUDE
291      *
292      * Yet another _alleged_ bug in TimeZone.getOffset(), a method that never
293      * should have been made public.  It's simply too hard to use correctly.
294      *
295      * The original test code failed to do the following:
296      * (1) Call Calendar.setTime() before getting the fields!
297      * (2) Use the right millis (as usual) for getOffset(); they were passing
298      *     in the MILLIS field, instead of the STANDARD MILLIS IN DAY.
299      * When you fix these two problems, the test passes, as expected.
300      */
301     public void Test4126678() {
302     // Note: this test depends on the PST time zone.
303     TimeZone initialZone = TimeZone.getDefault();
304         Calendar cal = Calendar.getInstance();
305         TimeZone tz = TimeZone.getTimeZone("PST");
306     TimeZone.setDefault(tz);
307         cal.setTimeZone(tz);
308
309         java.util.Calendar tempcal = java.util.Calendar.getInstance();
310         tempcal.clear();
311         tempcal.set(1998, Calendar.APRIL, 5, 10, 0);
312         Date dt = tempcal.getTime();
313     // the dt value is local time in PST.
314         if (!tz.inDaylightTime(dt))
315             errln("We're not in Daylight Savings Time and we should be.\n");
316
317         cal.setTime(dt);
318         int era = cal.get(Calendar.ERA);
319         int year = cal.get(Calendar.YEAR);
320         int month = cal.get(Calendar.MONTH);
321         int day = cal.get(Calendar.DATE);
322         int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
323         int millis = cal.get(Calendar.MILLISECOND) +
324             (cal.get(Calendar.SECOND) +
325              (cal.get(Calendar.MINUTE) +
326               (cal.get(Calendar.HOUR) * 60) * 60) * 1000) -
327             cal.get(Calendar.DST_OFFSET);
328
329         long offset = tz.getOffset(era, year, month, day, dayOfWeek, millis);
330         long raw_offset = tz.getRawOffset();
331         if (offset == raw_offset)
332             errln("Offsets should not match when in DST");
333
334     // restore the initial time zone so that this test case
335     // doesn't affect the others.
336     TimeZone.setDefault(initialZone);
337     }
338
339     /**
340      * TimeZone.getAvailableIDs(int) throws exception for certain values,
341      * due to a faulty constant in TimeZone.java.
342      */
343     public void Test4151406() {
344         int max = 0;
345         for (int h=-28; h<=30; ++h) {
346             // h is in half-hours from GMT; rawoffset is in millis
347             int rawoffset = h * 1800000;
348             int hh = (h<0) ? -h : h;
349             String hname = ((h<0) ? "GMT-" : "GMT+") +
350                 ((hh/2 < 10) ? "0" : "") +
351                 (hh/2) + ':' +
352                 ((hh%2==0) ? "00" : "30");
353             try {
354                 String[] ids = TimeZone.getAvailableIDs(rawoffset);
355                 if (ids.length > max) max = ids.length;
356                 logln(hname + ' ' + ids.length +
357                       ((ids.length > 0) ? (" e.g. " + ids[0]) : ""));
358             } catch (Exception e) {
359                 errln(hname + ' ' + "Fail: " + e);
360             }
361         }
362         logln("Maximum zones per offset = " + max);
363     }
364
365     public void Test4151429() {
366         try {
367             TimeZone tz = TimeZone.getTimeZone("GMT");
368             /*String name =*/ tz.getDisplayName(true, Integer.MAX_VALUE,
369                                             Locale.getDefault());
370             errln("IllegalArgumentException not thrown by TimeZone.getDisplayName()");
371         } catch(IllegalArgumentException e) {
372             System.out.print("");
373         }
374     }
375
376     /**
377      * SimpleTimeZone accepts illegal DST savings values.  These values
378      * must be non-zero.  There is no upper limit at this time.
379      */
380     public void Test4154525() {
381         final int GOOD = 1, BAD = 0;
382         int[] DATA = {
383             1, GOOD,
384             0, BAD,
385             -1, BAD,
386             60*60*1000, GOOD,
387             Integer.MIN_VALUE, BAD,
388             // Integer.MAX_VALUE, ?, // no upper limit on DST savings at this time
389         };
390         for (int i=0; i<DATA.length; i+=2) {
391             int savings = DATA[i];
392             boolean valid = DATA[i+1] == GOOD;
393             String method = null;
394             for (int j=0; j<2; ++j) {
395                 try {
396                     switch (j) {
397                     case 0:
398                         method = "constructor";
399                         SimpleTimeZone z = new SimpleTimeZone(0, "id",
400                             Calendar.JANUARY, 1, 0, 0,
401                             Calendar.MARCH, 1, 0, 0,
402                             savings); // <- what we're interested in
403                         break;
404                     case 1:
405                         method = "setDSTSavings()";
406                         z = new SimpleTimeZone(0, "GMT");
407                         z.setDSTSavings(savings);
408                         break;
409                     }
410                     if (valid) {
411                         logln("Pass: DST savings of " + savings + " accepted by " + method);
412                     } else {
413                         errln("Fail: DST savings of " + savings + " accepted by " + method);
414                     }
415                 } catch (IllegalArgumentException e) {
416                     if (valid) {
417                         errln("Fail: DST savings of " + savings + " to " + method + " gave " + e);
418                     } else {
419                         logln("Pass: DST savings of " + savings + " to " + method + " gave " + e);
420                     }
421                 }
422             }
423         }
424     }
425
426     /**
427      * SimpleTimeZone.hasSameRules() doesn't work for zones with no DST
428      * and different DST parameters.
429      */
430     public void Test4154537() {
431         // tz1 and tz2 have no DST and different rule parameters
432         SimpleTimeZone tz1 = new SimpleTimeZone(0, "1", 0, 0, 0, 0, 2, 0, 0, 0);
433         SimpleTimeZone tz2 = new SimpleTimeZone(0, "2", 1, 0, 0, 0, 3, 0, 0, 0);
434         // tza and tzA have the same rule params
435         SimpleTimeZone tza = new SimpleTimeZone(0, "a", 0, 1, 0, 0, 3, 2, 0, 0);
436         SimpleTimeZone tzA = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 3, 2, 0, 0);
437         // tzb differs from tza
438         SimpleTimeZone tzb = new SimpleTimeZone(0, "b", 0, 1, 0, 0, 3, 1, 0, 0);
439         if (tz1.useDaylightTime() || tz2.useDaylightTime() ||
440             !tza.useDaylightTime() || !tzA.useDaylightTime() ||
441             !tzb.useDaylightTime()) {
442             errln("Test is broken -- rewrite it");
443         }
444         if (!tza.hasSameRules(tzA) || tza.hasSameRules(tzb)) {
445             errln("Fail: hasSameRules() broken for zones with rules");
446         }
447         if (!tz1.hasSameRules(tz2)) {
448             errln("Fail: hasSameRules() returns false for zones without rules");
449             errln("zone 1 = " + tz1);
450             errln("zone 2 = " + tz2);
451         }
452     }
453
454     /**
455      * SimpleTimeZone constructors, setStartRule(), and setEndRule() don't
456      * check for out-of-range arguments.
457      */
458     public void Test4154542() {
459         final int GOOD = 1;
460         final int BAD  = 0;
461
462         final int GOOD_MONTH       = Calendar.JANUARY;
463         final int GOOD_DAY         = 1;
464         final int GOOD_DAY_OF_WEEK = Calendar.SUNDAY;
465         final int GOOD_TIME        = 0;
466
467         int[] DATA = {
468             GOOD, Integer.MIN_VALUE,    0,  Integer.MAX_VALUE,   Integer.MIN_VALUE,
469             GOOD, Calendar.JANUARY,    -5,  Calendar.SUNDAY,     0,
470             GOOD, Calendar.DECEMBER,    5,  Calendar.SATURDAY,   24*60*60*1000-1,
471             BAD,  Calendar.DECEMBER,    5,  Calendar.SATURDAY,   24*60*60*1000+1,
472             BAD,  Calendar.DECEMBER,    5,  Calendar.SATURDAY,  -1,
473             BAD,  Calendar.JANUARY,    -6,  Calendar.SUNDAY,     0,
474             BAD,  Calendar.DECEMBER,    6,  Calendar.SATURDAY,   24*60*60*1000,
475             GOOD, Calendar.DECEMBER,    1,  0,                   0,
476             GOOD, Calendar.DECEMBER,   31,  0,                   0,
477             BAD,  Calendar.APRIL,      31,  0,                   0,
478             BAD,  Calendar.DECEMBER,   32,  0,                   0,
479             BAD,  Calendar.JANUARY-1,   1,  Calendar.SUNDAY,     0,
480             BAD,  Calendar.DECEMBER+1,  1,  Calendar.SUNDAY,     0,
481             GOOD, Calendar.DECEMBER,   31, -Calendar.SUNDAY,     0,
482             GOOD, Calendar.DECEMBER,   31, -Calendar.SATURDAY,   0,
483             BAD,  Calendar.DECEMBER,   32, -Calendar.SATURDAY,   0,
484             BAD,  Calendar.DECEMBER,  -32, -Calendar.SATURDAY,   0,
485             BAD,  Calendar.DECEMBER,   31, -Calendar.SATURDAY-1, 0,
486         };
487         SimpleTimeZone zone = new SimpleTimeZone(0, "Z");
488         for (int i=0; i<DATA.length; i+=5) {
489             boolean shouldBeGood = (DATA[i] == GOOD);
490             int month     = DATA[i+1];
491             int day       = DATA[i+2];
492             int dayOfWeek = DATA[i+3];
493             int time      = DATA[i+4];
494
495             Exception ex = null;
496             try {
497                 zone.setStartRule(month, day, dayOfWeek, time);
498             } catch (IllegalArgumentException e) {
499                 ex = e;
500             }
501             if ((ex == null) != shouldBeGood) {
502                 errln("setStartRule(month=" + month + ", day=" + day +
503                       ", dayOfWeek=" + dayOfWeek + ", time=" + time +
504                       (shouldBeGood ? (") should work but throws " + ex)
505                        : ") should fail but doesn't"));
506             }
507
508             ex = null;
509             try {
510                 zone.setEndRule(month, day, dayOfWeek, time);
511             } catch (IllegalArgumentException e) {
512                 ex = e;
513             }
514             if ((ex == null) != shouldBeGood) {
515                 errln("setEndRule(month=" + month + ", day=" + day +
516                       ", dayOfWeek=" + dayOfWeek + ", time=" + time +
517                       (shouldBeGood ? (") should work but throws " + ex)
518                        : ") should fail but doesn't"));
519             }
520
521             ex = null;
522             try {
523                 /*SimpleTimeZone temp =*/ new SimpleTimeZone(0, "Z",
524                         month, day, dayOfWeek, time,
525                         GOOD_MONTH, GOOD_DAY, GOOD_DAY_OF_WEEK, GOOD_TIME);
526             } catch (IllegalArgumentException e) {
527                 ex = e;
528             }
529             if ((ex == null) != shouldBeGood) {
530                 errln("SimpleTimeZone(month=" + month + ", day=" + day +
531                       ", dayOfWeek=" + dayOfWeek + ", time=" + time +
532                       (shouldBeGood ? (", <end>) should work but throws " + ex)
533                        : ", <end>) should fail but doesn't"));
534             }
535
536             ex = null;
537             try {
538                 /*SimpleTimeZone temp = */new SimpleTimeZone(0, "Z",
539                         GOOD_MONTH, GOOD_DAY, GOOD_DAY_OF_WEEK, GOOD_TIME,
540                         month, day, dayOfWeek, time);
541                // temp = null;
542             } catch (IllegalArgumentException e) {
543                 ex = e;
544             }
545             if ((ex == null) != shouldBeGood) {
546                 errln("SimpleTimeZone(<start>, month=" + month + ", day=" + day +
547                       ", dayOfWeek=" + dayOfWeek + ", time=" + time +
548                       (shouldBeGood ? (") should work but throws " + ex)
549                        : ") should fail but doesn't"));
550             }
551         }
552     }
553
554     /**
555      * SimpleTimeZone.getOffset accepts illegal arguments.
556      */
557     public void Test4154650() {
558         final int GOOD=1, BAD=0;
559         final int GOOD_ERA=GregorianCalendar.AD, GOOD_YEAR=1998, GOOD_MONTH=Calendar.AUGUST;
560         final int GOOD_DAY=2, GOOD_DOW=Calendar.SUNDAY, GOOD_TIME=16*3600000;
561         int[] DATA = {
562             GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
563
564             GOOD, GregorianCalendar.BC, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
565             GOOD, GregorianCalendar.AD, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
566             BAD,  GregorianCalendar.BC-1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
567             BAD,  GregorianCalendar.AD+1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
568
569             GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, GOOD_DAY, GOOD_DOW, GOOD_TIME,
570             GOOD, GOOD_ERA, GOOD_YEAR, Calendar.DECEMBER, GOOD_DAY, GOOD_DOW, GOOD_TIME,
571             BAD,  GOOD_ERA, GOOD_YEAR, Calendar.JANUARY-1, GOOD_DAY, GOOD_DOW, GOOD_TIME,
572             BAD,  GOOD_ERA, GOOD_YEAR, Calendar.DECEMBER+1, GOOD_DAY, GOOD_DOW, GOOD_TIME,
573
574             GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 1, GOOD_DOW, GOOD_TIME,
575             GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 31, GOOD_DOW, GOOD_TIME,
576             BAD,  GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 0, GOOD_DOW, GOOD_TIME,
577             BAD,  GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 32, GOOD_DOW, GOOD_TIME,
578
579             GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SUNDAY, GOOD_TIME,
580             GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SATURDAY, GOOD_TIME,
581             BAD,  GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SUNDAY-1, GOOD_TIME,
582             BAD,  GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SATURDAY+1, GOOD_TIME,
583
584             GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 0,
585             GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000-1,
586             BAD,  GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, -1,
587             BAD,  GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000,
588         };
589
590         TimeZone tz = TimeZone.getDefault();
591         for (int i=0; i<DATA.length; i+=7) {
592             boolean good = DATA[i] == GOOD;
593             IllegalArgumentException e = null;
594             try {
595                 /*int offset =*/ tz.getOffset(DATA[i+1], DATA[i+2], DATA[i+3],
596                                           DATA[i+4], DATA[i+5], DATA[i+6]);
597                 //offset = 0;
598            } catch (IllegalArgumentException ex) {
599                 e = ex;
600             }
601             if (good != (e == null)) {
602                 errln("Fail: getOffset(" +
603                       DATA[i+1] + ", " + DATA[i+2] + ", " + DATA[i+3] + ", " +
604                       DATA[i+4] + ", " + DATA[i+5] + ", " + DATA[i+6] +
605                       (good ? (") threw " + e) : ") accepts invalid args"));
606             }
607         }
608     }
609
610     /**
611      * TimeZone constructors allow null IDs.
612      */
613     public void Test4159922() {
614         TimeZone z = null;
615
616         // TimeZone API.  Only hasSameRules() and setDefault() should
617         // allow null.
618         try {
619             z = TimeZone.getTimeZone(null);
620             errln("FAIL: Null allowed in getTimeZone");
621         } catch (NullPointerException e) {
622             System.out.print("");
623         }
624         z = TimeZone.getTimeZone("GMT");
625         try {
626         // {dlf} requiring cast for disambiguation is ok for compatibility since null
627         // is not a valid argument to this API
628             z.getDisplayName(false, TimeZone.SHORT, (ULocale)null);
629             errln("FAIL: Null allowed in getDisplayName(3)");
630         } catch (NullPointerException e) {
631             System.out.print("");
632         }
633         try {
634         // {dlf} see above
635             z.getDisplayName((ULocale)null);
636             errln("FAIL: Null allowed in getDisplayName(1)");
637         } catch (NullPointerException e) {
638             System.out.print("");
639         }
640         try {
641             if (z.hasSameRules(null)) {
642                 errln("FAIL: hasSameRules returned true");
643             }
644         } catch (NullPointerException e) {
645             errln("FAIL: Null NOT allowed in hasSameRules");
646         }
647         try {
648             z.inDaylightTime(null);
649             errln("FAIL: Null allowed in inDaylightTime");
650         } catch (NullPointerException e) {
651             System.out.print("");
652         }
653         try {
654             z.setID(null);
655             errln("FAIL: Null allowed in setID");
656         } catch (NullPointerException e) {
657             System.out.print("");
658         }
659
660         TimeZone save = TimeZone.getDefault();
661         try {
662             TimeZone.setDefault(null);
663         } catch (NullPointerException e) {
664             errln("FAIL: Null NOT allowed in setDefault");
665         } finally {
666             TimeZone.setDefault(save);
667         }
668
669         // SimpleTimeZone API
670         SimpleTimeZone s = null;
671         try {
672             s = new SimpleTimeZone(0, null);
673             errln("FAIL: Null allowed in SimpleTimeZone(2)");
674         } catch (NullPointerException e) {
675             System.out.print("");
676         }
677         try {
678             s = new SimpleTimeZone(0, null, 0, 1, 0, 0, 0, 1, 0, 0);
679             errln("FAIL: Null allowed in SimpleTimeZone(10)");
680         } catch (NullPointerException e) {
681             System.out.print("");
682         }
683         try {
684             s = new SimpleTimeZone(0, null, 0, 1, 0, 0, 0, 1, 0, 0, 1000);
685             errln("FAIL: Null allowed in SimpleTimeZone(11)");
686         } catch (NullPointerException e) {
687             System.out.print("");
688         }
689         if(s!=null){
690             errln("FAIL: Did not get the expected Exception");
691         }
692     }
693
694     /**
695      * TimeZone broken at midnight.  The TimeZone code fails to handle
696      * transitions at midnight correctly.
697      */
698     public void Test4162593() {
699         SimpleDateFormat fmt = new SimpleDateFormat("z", Locale.US);
700         final int ONE_HOUR = 60*60*1000;
701         final float H = (float) ONE_HOUR;
702         TimeZone initialZone = TimeZone.getDefault();
703         SimpleDateFormat sdf = new SimpleDateFormat("MMM dd yyyy HH:mm z");
704
705         SimpleTimeZone asuncion = new SimpleTimeZone(-4*ONE_HOUR, "America/Asuncion" /*PY%sT*/,
706             Calendar.OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR,
707             Calendar.MARCH, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR);
708
709         /* Zone
710          * Starting time
711          * Transition expected between start+1H and start+2H
712          */
713         Object[] DATA = {
714             new SimpleTimeZone(2*ONE_HOUR, "Asia/Damascus" /*EE%sT*/,
715                 Calendar.APRIL, 1, 0 /*DOM*/, 0*ONE_HOUR,
716                 Calendar.OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR),
717             new int[] {1998, Calendar.SEPTEMBER, 30, 22, 0},
718             Boolean.TRUE,
719
720             asuncion,
721             new int[] {2000, Calendar.FEBRUARY, 28, 22, 0},
722             Boolean.FALSE,
723
724             asuncion,
725             new int[] {2000, Calendar.FEBRUARY, 29, 22, 0},
726             Boolean.TRUE,
727         };
728
729         String[] zone = new String[4];
730
731         for (int j=0; j<DATA.length; j+=3) {
732             TimeZone tz = (TimeZone)DATA[j];
733             TimeZone.setDefault(tz);
734             fmt.setTimeZone(tz);
735             sdf.setTimeZone(tz);
736
737             // Must construct the Date object AFTER setting the default zone
738             int[] p = (int[])DATA[j+1];
739             Calendar cal = Calendar.getInstance();
740             cal.clear();
741             cal.set(p[0], p[1], p[2], p[3], p[4]);
742             long start = cal.getTime().getTime();
743             boolean transitionExpected = ((Boolean)DATA[j+2]).booleanValue();
744
745             logln(tz.getID() + ":");
746             for (int i=0; i<4; ++i) {
747                 Date d = new Date(start + i*ONE_HOUR);
748                 zone[i] = fmt.format(d);
749                 logln("" + i + ": " + sdf.format(d) + " => " + zone[i] +
750                       " (" + d.getTime()/H + ")");
751             }
752             cal.set(p[0], p[1], p[2], 0, 0);
753             for (int i=0; i<4; ++i) {
754                 int h = 22+i;
755                 int dom = p[2]+(h>=24?1:0);
756                 h %= 24;
757                 int ms = h*ONE_HOUR;
758                 cal.clear();
759                 cal.set(p[0], p[1], dom, 0, 0);
760                 int off = tz.getOffset(GregorianCalendar.AD,
761                                        cal.get(Calendar.YEAR),
762                                        cal.get(Calendar.MONTH),
763                                        cal.get(Calendar.DATE),
764                                        cal.get(Calendar.DAY_OF_WEEK),
765                                        ms);
766                 cal.add(Calendar.HOUR, h);
767                 int dstOffset = cal.get(Calendar.DST_OFFSET);
768                 logln("h=" + h + "; dom=" + dom +
769                       "; ZONE_OFFSET=" + cal.get(Calendar.ZONE_OFFSET)/H +
770                       "; DST_OFFSET=" + dstOffset/H +
771                       "; getOffset()=" + off/H +
772                       " (" + cal.getTime().getTime()/H + ")");
773             }
774             if (zone[0].equals(zone[1]) &&
775                 (zone[1].equals(zone[2]) != transitionExpected) &&
776                 zone[2].equals(zone[3])) {
777                 logln("Ok: transition " + transitionExpected);
778             } else {
779                 errln("FAIL: expected " +
780                       (transitionExpected?"transition":"no transition"));
781             }
782         }
783
784     // restore the initial time zone so that this test case
785     // doesn't affect the others.
786     TimeZone.setDefault(initialZone);
787     }
788
789     /**
790      * TimeZone broken in last hour of year
791      */
792     public void Test4173604() {
793         TimeZone pst = TimeZone.getTimeZone("PST");
794         int o22 = pst.getOffset(1, 1998, 11, 31, Calendar.THURSDAY, 22*60*60*1000);
795         int o23 = pst.getOffset(1, 1998, 11, 31, Calendar.THURSDAY, 23*60*60*1000);
796         int o00 = pst.getOffset(1, 1999, 0, 1, Calendar.FRIDAY, 0);
797         if (o22 != o23 || o22 != o00) {
798             errln("Offsets should be the same (for PST), but got: " +
799                   "12/31 22:00 " + o22 +
800                   ", 12/31 23:00 " + o23 +
801                   ", 01/01 00:00 " + o00);
802         }
803
804         GregorianCalendar cal = new GregorianCalendar();
805         cal.setTimeZone(pst);
806         cal.clear();
807         cal.set(1998, Calendar.JANUARY, 1);
808         int lastDST = cal.get(Calendar.DST_OFFSET);
809         int transitions = 0;
810         int delta = 5;
811         while (cal.get(Calendar.YEAR) < 2000) {
812             cal.add(Calendar.MINUTE, delta);
813             if (cal.get(Calendar.DST_OFFSET) != lastDST) {
814                 ++transitions;
815                 Calendar t = (Calendar)cal.clone();
816                 t.add(Calendar.MINUTE, -delta);
817                 logln(t.getTime() + "  " + t.get(Calendar.DST_OFFSET));
818                 logln(cal.getTime() + "  " + (lastDST=cal.get(Calendar.DST_OFFSET)));
819             }
820         }
821         if (transitions != 4) {
822             errln("Saw " + transitions + " transitions; should have seen 4");
823         }
824     }
825
826     /**
827      * getDisplayName doesn't work with unusual savings/offsets.
828      */
829     public void Test4176686() {
830         // Construct a zone that does not observe DST but
831         // that does have a DST savings (which should be ignored).
832         int offset = 90 * 60000; // 1:30
833         SimpleTimeZone z1 = new SimpleTimeZone(offset, "_std_zone_");
834         z1.setDSTSavings(45 * 60000); // 0:45
835
836         // Construct a zone that observes DST for the first 6 months.
837         SimpleTimeZone z2 = new SimpleTimeZone(offset, "_dst_zone_");
838         z2.setDSTSavings(45 * 60000); // 0:45
839         z2.setStartRule(Calendar.JANUARY, 1, 0);
840         z2.setEndRule(Calendar.JULY, 1, 0);
841
842         // Also check DateFormat
843         DateFormat fmt1 = new SimpleDateFormat("z");
844         fmt1.setTimeZone(z1); // Format uses standard zone
845         DateFormat fmt2 = new SimpleDateFormat("z");
846         fmt2.setTimeZone(z2); // Format uses DST zone
847         java.util.Calendar tempcal = java.util.Calendar.getInstance();
848         tempcal.clear();
849         tempcal.set(1970, Calendar.FEBRUARY, 1);
850         Date dst = tempcal.getTime(); // Time in DST
851         tempcal.set(1970, Calendar.AUGUST, 1);
852         Date std = tempcal.getTime(); // Time in standard
853
854         // Description, Result, Expected Result
855         String[] DATA = {
856             "getDisplayName(false, SHORT)/std zone",
857             z1.getDisplayName(false, TimeZone.SHORT), "GMT+1:30",
858             "getDisplayName(false, LONG)/std zone",
859             z1.getDisplayName(false, TimeZone.LONG ), "GMT+01:30",
860             "getDisplayName(true, SHORT)/std zone",
861             z1.getDisplayName(true, TimeZone.SHORT), "GMT+1:30",
862             "getDisplayName(true, LONG)/std zone",
863             z1.getDisplayName(true, TimeZone.LONG ), "GMT+01:30",
864             "getDisplayName(false, SHORT)/dst zone",
865             z2.getDisplayName(false, TimeZone.SHORT), "GMT+1:30",
866             "getDisplayName(false, LONG)/dst zone",
867             z2.getDisplayName(false, TimeZone.LONG ), "GMT+01:30",
868             "getDisplayName(true, SHORT)/dst zone",
869             z2.getDisplayName(true, TimeZone.SHORT), "GMT+2:15",
870             "getDisplayName(true, LONG)/dst zone",
871             z2.getDisplayName(true, TimeZone.LONG ), "GMT+02:15",
872             "DateFormat.format(std)/std zone", fmt1.format(std), "GMT+1:30",
873             "DateFormat.format(dst)/std zone", fmt1.format(dst), "GMT+1:30",
874             "DateFormat.format(std)/dst zone", fmt2.format(std), "GMT+1:30",
875             "DateFormat.format(dst)/dst zone", fmt2.format(dst), "GMT+2:15",
876         };
877
878         for (int i=0; i<DATA.length; i+=3) {
879             if (!DATA[i+1].equals(DATA[i+2])) {
880                 errln("FAIL: " + DATA[i] + " -> " + DATA[i+1] + ", exp " + DATA[i+2]);
881             }
882         }
883     }
884
885     /**
886      * SimpleTimeZone allows invalid DOM values.
887      */
888     // Current orgnaization of data in zoneinfor.res allows negative
889     // values from DOM so comment these tests out
890     
891     public void Test4184229() {
892         SimpleTimeZone zone = null;
893         try {
894             zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0);
895             errln("Failed. No exception has been thrown for DOM -1 startDay");
896         } catch(IllegalArgumentException e) {
897             logln("(a) " + e.getMessage());
898         }
899         try {
900             zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0);
901             errln("Failed. No exception has been thrown for DOM -1 endDay");
902         } catch(IllegalArgumentException e) {
903             logln("(b) " + e.getMessage());
904         }
905         try {
906             zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0, 1000);
907             errln("Failed. No exception has been thrown for DOM -1 startDay +savings");
908         } catch(IllegalArgumentException e) {
909             logln("(c) " + e.getMessage());
910         }
911         try {
912             zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0, 1000);
913             errln("Failed. No exception has been thrown for DOM -1 endDay +savings");
914         } catch(IllegalArgumentException e) {
915             logln("(d) " + e.getMessage());
916         }
917         // Make a valid constructor call for subsequent tests.
918
919         zone = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 0, 1, 0, 0);
920         
921         try {
922             zone.setStartRule(0, -1, 0, 0);
923             errln("Failed. No exception has been thrown for DOM -1 setStartRule +savings");
924         } catch(IllegalArgumentException e) {
925             logln("(e) " + e.getMessage());
926         }
927         try {
928             zone.setStartRule(0, -1, 0);
929             errln("Failed. No exception has been thrown for DOM -1 setStartRule");
930         } catch(IllegalArgumentException e) {
931             logln("(f) " + e.getMessage());
932         }
933         try {
934             zone.setEndRule(0, -1, 0, 0);
935             errln("Failed. No exception has been thrown for DOM -1 setEndRule +savings");
936         } catch(IllegalArgumentException e) {
937             logln("(g) " + e.getMessage());
938         }
939         try {
940             zone.setEndRule(0, -1, 0);
941             errln("Failed. No exception has been thrown for DOM -1 setEndRule");
942         } catch(IllegalArgumentException e) {
943             logln("(h) " + e.getMessage());
944         }
945         
946     }
947
948     /**
949      * SimpleTimeZone.getOffset() throws IllegalArgumentException when to get
950      * of 2/29/1996 (leap day).
951      */
952     public void Test4208960 () {
953     TimeZone tz = TimeZone.getTimeZone("PST");
954     try {
955         /*int offset =*/ tz.getOffset(GregorianCalendar.AD, 1996, Calendar.FEBRUARY, 29,
956                       Calendar.THURSDAY, 0);
957         //offset = 0;
958     } catch (IllegalArgumentException e) {
959         errln("FAILED: to get TimeZone.getOffset(2/29/96)");
960     }
961     try {
962         /*int offset =*/ tz.getOffset(GregorianCalendar.AD, 1997, Calendar.FEBRUARY, 29,
963                       Calendar.THURSDAY, 0);
964         //offset = 0;
965         warnln("FAILED: TimeZone.getOffset(2/29/97) expected to throw Exception.");
966     } catch (IllegalArgumentException e) {
967         logln("got IllegalArgumentException");
968     }
969     }
970
971     /**
972      * Test to see if DateFormat understands zone equivalency groups.  It
973      * might seem that this should be a DateFormat test, but it's really a
974      * TimeZone test -- the changes to DateFormat are minor.
975      *
976      * We use two known, zones that are equivalent, where one zone has
977      * localized name data, and the other doesn't, in some locale.
978      */
979     public void TestJ449() {
980         // not used String str;
981
982         // Modify the following three as necessary.  The two IDs must
983         // specify two zones in the same equivalency group.  One must have
984         // locale data in 'loc'; the other must not.
985         String idWithLocaleData = "America/Los_Angeles";
986         String idWithoutLocaleData = "PST"; // "US/Pacific";
987         Locale loc = new Locale("en", "", "");
988
989         TimeZone zoneWith = TimeZone.getTimeZone(idWithLocaleData);
990         TimeZone zoneWithout = TimeZone.getTimeZone(idWithoutLocaleData);
991         // Make sure we got valid zones
992         if (!(zoneWith.getID().equals(idWithLocaleData) &&
993               zoneWithout.getID().equals(idWithoutLocaleData))) {
994             warnln("Fail: Unable to create zones");
995         } else {
996             GregorianCalendar calWith = new GregorianCalendar(zoneWith);
997             GregorianCalendar calWithout = new GregorianCalendar(zoneWithout);
998             SimpleDateFormat fmt =
999                 new SimpleDateFormat("MMM d yyyy hh:mm a zzz", loc);
1000             Date date = new Date(0L);
1001             fmt.setCalendar(calWith);
1002             String strWith = fmt.format(date);
1003             fmt.setCalendar(calWithout);
1004             String strWithout = fmt.format(date);
1005             if (strWith.equals(strWithout)) {
1006                 logln("Ok: " + idWithLocaleData + " -> " +
1007                       strWith + "; " + idWithoutLocaleData + " -> " +
1008                       strWithout);
1009             } else {
1010                 errln("FAIL: " + idWithLocaleData + " -> " +
1011                       strWith + "; " + idWithoutLocaleData + " -> " +
1012                       strWithout);
1013             }
1014         }
1015     }
1016
1017     /**
1018      * getOffset returns wrong offset for days in early 20th century
1019      */
1020     public void TestJ5134() {
1021         GregorianCalendar testCal = (GregorianCalendar)Calendar.getInstance();
1022         TimeZone icuEastern = TimeZone.getTimeZone("America/New_York");        
1023         testCal.setTimeZone(icuEastern);
1024         testCal.set(1900, Calendar.JANUARY, 1, 0, 0, 0);
1025         long time = testCal.getTimeInMillis();
1026
1027         int offset = icuEastern.getOffset(time);
1028         if (offset != -18000000) {
1029             errln("FAIL: UTC offset in time zone America/New_York on Jan 1, 1900 -> " + offset);
1030         }
1031         boolean isDst = icuEastern.inDaylightTime(new Date(time));
1032         if (isDst) {
1033             errln("FAIL: DST is observed in time zone America/New_York on Jan 1, 1900");
1034         }
1035
1036         if (System.getProperty("java.vendor", "").startsWith("IBM") &&
1037             System.getProperty("java.version", "").equals("1.4.1")) {
1038             // IBM JDK 1.4.1 has a bug and fails to run this test case.
1039             return;
1040         }
1041         java.util.TimeZone jdkEastern = java.util.TimeZone.getTimeZone("America/New_York");
1042         // Compare offset and DST observation with JDK and ICU for 50 years since 1900
1043         testCal.add(Calendar.YEAR, 50);
1044         long endTime = testCal.getTimeInMillis();
1045         int jdkOffset;
1046         boolean isDstJdk;
1047         while (time < endTime) {
1048             offset = icuEastern.getOffset(time);
1049             jdkOffset = jdkEastern.getOffset(time);
1050             if (offset != jdkOffset) {
1051                 errln("FAIL: Incompatible UTC offset -> JDK:" + jdkOffset + "/ICU:" + offset + " [" + time + "]");
1052             }
1053             Date d = new Date(time);
1054             isDst = icuEastern.inDaylightTime(d);
1055             isDstJdk = jdkEastern.inDaylightTime(d);
1056             if (isDst != isDstJdk) {
1057                 errln("FAIL: Incompatible DST -> JDK:" + isDstJdk + "/ICU:" + isDst + " [" + time + "]");
1058             }
1059             time += 24*60*60*1000L; // increment 1 day
1060         }
1061     }
1062
1063     /**
1064      * Test setRawOffset works OK with system timezone
1065      */
1066     public void TestT5280() {
1067         String[] tzids = TimeZone.getAvailableIDs();
1068         for (int i = 0; i < tzids.length; i++) {
1069             TimeZone tz = TimeZone.getTimeZone(tzids[i]);
1070             boolean useDst = tz.useDaylightTime();
1071
1072             // Increase offset for 30 minutes
1073             int newRawOffset = tz.getRawOffset() + 30*60*1000;
1074             try {
1075                 tz.setRawOffset(newRawOffset);
1076             } catch (Exception e) {
1077                 errln("FAIL: setRawOffset throws an exception");
1078             }
1079             int offset = tz.getRawOffset();
1080             if (offset != newRawOffset) {
1081                 errln("FAIL: Modified zone(" + tz.getID() + ") - getRawOffset returns " + offset + "/ Expected: " + newRawOffset);
1082             }
1083             // Ticket#5917
1084             // Check if DST observation status is not unexpectedly changed.
1085             boolean newDst = tz.useDaylightTime();
1086             if (useDst != newDst) {
1087                 errln("FAIL: Modified zone(" + tz.getID() + ") - useDaylightTime has changed from " + useDst + " to " + newDst);
1088             }
1089             // Make sure the offset is preserved in a clone
1090             TimeZone tzClone = (TimeZone)tz.clone();
1091             offset = tzClone.getRawOffset();
1092             if (offset != newRawOffset) {
1093                 errln("FAIL: Cloned modified zone(" + tz.getID() + ") - getRawOffset returns " + offset + "/ Expected: " + newRawOffset);
1094             }
1095         }
1096     }
1097
1098     /*
1099      * Zone ID is not set by a SimpleTimeZone constructor
1100      */
1101     public void TestT5432() {
1102         String tzid = "MyZone";
1103         SimpleTimeZone stz;
1104
1105         // 2-arg constructor
1106         stz = new SimpleTimeZone(0, tzid);
1107         if (!tzid.equals(stz.getID())) {
1108             errln("FAIL: Bad zone id (" + stz.getID() + ") is returned - expected ("
1109                     + tzid + ") [2-arg constructor]");
1110         }
1111
1112         // 10-arg constructor
1113         stz = new SimpleTimeZone(0, tzid, 3, -1, 1, 3600000, 9, -1, 1, 3600000);
1114         if (!tzid.equals(stz.getID())) {
1115             errln("FAIL: Bad zone id (" + stz.getID() + ") is returned - expected ("
1116                     + tzid + ") [10-arg constructor]");
1117         }
1118
1119         // 11-arg constructor
1120         stz = new SimpleTimeZone(0, tzid, 3, -1, 1, 3600000, 9, -1, 1, 3600000, 3600000);
1121         if (!tzid.equals(stz.getID())) {
1122             errln("FAIL: Bad zone id (" + stz.getID() + ") is returned - expected ("
1123                     + tzid + ") [11-arg constructor]");
1124         }
1125
1126         // 13-arg constructor - this version had a problem reported by trac#5432
1127         stz = new SimpleTimeZone(0, tzid, 3, -1, 1, 3600000, SimpleTimeZone.WALL_TIME,
1128                 9, -1, 1, 3600000, SimpleTimeZone.WALL_TIME, 3600000);
1129         if (!tzid.equals(stz.getID())) {
1130             errln("FAIL: Bad zone id (" + stz.getID() + ") is returned - expected ("
1131                     + tzid + ") [13-arg constructor]");
1132         }
1133     }
1134     
1135     // test bug #4265
1136     public void TestJohannesburg() {
1137         String j_id="Africa/Johannesburg";
1138         TimeZone johannesburg = TimeZone.getTimeZone(j_id);
1139         final int ONE_HOUR = 60*60*1000;
1140         int expectedOffset = ONE_HOUR*2;  // GMT+2 - NO DST
1141         int offset = johannesburg.getOffset(GregorianCalendar.AD,2007,Calendar.JULY,5,Calendar.THURSDAY,0);        
1142         
1143         if(offset != expectedOffset) {
1144             errln("FAIL: zone " + j_id +" returned offset in July " + offset +", expected "+expectedOffset);
1145         } else {
1146             logln("OK: zone " + j_id +" returned offset in July: " + offset);
1147         }
1148
1149         int offset2 = johannesburg.getOffset(GregorianCalendar.AD,2007,Calendar.DECEMBER,12,Calendar.WEDNESDAY,0);
1150
1151         if(offset2 != expectedOffset) {
1152             errln("FAIL: zone " + j_id +" returned offset in December " + offset2 +", expected "+expectedOffset);
1153         } else {
1154             logln("OK: zone " + j_id +" returned offset in December: " + offset2);
1155         }
1156     }
1157
1158     public void TestT7107() {
1159         Thread[] workers = new Thread[20];
1160         for (int i = 0 ; i < workers.length; i++) {
1161             workers[i] = new Thread(new Runnable() {
1162                 public void run() {
1163                     for (int j = 0; j < 10000; j++) {
1164                         try {
1165                             com.ibm.icu.util.TimeZone.getTimeZone("GMT").getDisplayName();
1166                         } catch (Exception e) {
1167                             errln("FAIL: Caught an exception " + e);
1168                         }
1169                     }
1170                 }
1171             });
1172         }
1173         for (Thread wk : workers) {
1174             wk.start();
1175         }
1176         for (Thread wk : workers) {
1177             try {
1178                 wk.join();
1179             } catch (InterruptedException ie) {
1180                 
1181             }
1182         }
1183     }
1184 }
1185
1186 //eof