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