< prev index next >

test/jdk/java/util/TimeZone/TimeZoneTest.java

Print this page

 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 /*
 25  * @test
 26  * @bug 4028006 4044013 4096694 4107276 4107570 4112869 4130885 7039469 7126465 7158483
 27  *      8008577 8077685 8098547 8133321 8138716 8148446 8151876 8159684 8166875 8181157
 28  *      8228469 8274407 8285844 8305113
 29  * @modules java.base/sun.util.resources
 30  * @library /java/text/testlib
 31  * @summary test TimeZone
 32  * @run main TimeZoneTest -verbose
 33  */
 34 
 35 import java.io.*;
 36 import java.text.*;
 37 import java.util.*;
 38 import sun.util.resources.LocaleData;
 39 
 40 public class TimeZoneTest extends IntlTest




 41 {
 42     static final int millisPerHour = 3600000;
 43 
 44     public static void main(String[] args) throws Exception {
 45         new TimeZoneTest().run(args);
 46     }
 47 
 48     /**
 49      * Bug 4130885
 50      * Certain short zone IDs, used since 1.1.x, are incorrect.
 51      *
 52      * The worst of these is:
 53      *
 54      * "CAT" (Central African Time) should be GMT+2:00, but instead returns a
 55      * zone at GMT-1:00. The zone at GMT-1:00 should be called EGT, CVT, EGST,
 56      * or AZOST, depending on which zone is meant, but in no case is it CAT.
 57      *
 58      * Other wrong zone IDs:
 59      *
 60      * ECT (European Central Time) GMT+1:00: ECT is Ecuador Time,
 61      * GMT-5:00. European Central time is abbreviated CEST.
 62      *
 63      * SST (Solomon Island Time) GMT+11:00. SST is actually Samoa Standard Time,
 64      * GMT-11:00. Solomon Island time is SBT.
 65      *
 66      * NST (New Zealand Time) GMT+12:00. NST is the abbreviation for
 67      * Newfoundland Standard Time, GMT-3:30. New Zealanders use NZST.

 83      * ART (should be EET)
 84      * MET (should be IRST)
 85      * NET (should be AMST)
 86      * PLT (should be PKT)
 87      * BST (should be BDT)
 88      * VST (should be ICT)
 89      * CTT (should be CST) +
 90      * ACT (should be CST) +
 91      * AET (should be EST) +
 92      * MIT (should be WST) +
 93      * IET (should be EST) +
 94      * PRT (should be AST) +
 95      * CNT (should be NST)
 96      * AGT (should be ARST)
 97      * BET (should be EST) +
 98      *
 99      * + A zone with the correct name already exists and means something
100      * else. E.g., EST usually indicates the US Eastern zone, so it cannot be
101      * used for Brazil (BET).
102      */

103     public void TestShortZoneIDs() throws Exception {
104 
105         ZoneDescriptor[] JDK_116_REFERENCE_LIST = {
106             new ZoneDescriptor("MIT", 780, false), // Samoa no longer observes DST starting 2021b
107             new ZoneDescriptor("HST", -600, false),
108             new ZoneDescriptor("AST", -540, true),
109             new ZoneDescriptor("PST", -480, true),
110             new ZoneDescriptor("PNT", -420, false),
111             new ZoneDescriptor("MST", -420, false),
112             new ZoneDescriptor("CST", -360, true),
113             new ZoneDescriptor("IET", -300, true),
114             new ZoneDescriptor("EST", -300, false),
115             new ZoneDescriptor("PRT", -240, false),
116             new ZoneDescriptor("CNT", -210, true),
117             new ZoneDescriptor("AGT", -180, false),
118             new ZoneDescriptor("BET", -180, false),
119             // new ZoneDescriptor("CAT", -60, false), // Wrong:
120             // As of bug 4130885, fix CAT (Central Africa)
121             new ZoneDescriptor("CAT", 120, false), // Africa/Harare
122             new ZoneDescriptor("GMT", 0, false),

137             new ZoneDescriptor("AET", 600, true),
138             new ZoneDescriptor("SST", 660, false),
139             // new ZoneDescriptor("NST", 720, false),
140             // As of bug 4130885, fix NST (New Zealand)
141             new ZoneDescriptor("NST", 720, true), // Pacific/Auckland
142         };
143 
144         Map<String, ZoneDescriptor> hash = new HashMap<>();
145 
146         String[] ids = TimeZone.getAvailableIDs();
147         for (String id : ids) {
148             if (id.length() == 3) {
149                 hash.put(id, new ZoneDescriptor(TimeZone.getTimeZone(id)));
150             }
151         }
152 
153         for (int i = 0; i < JDK_116_REFERENCE_LIST.length; ++i) {
154             ZoneDescriptor referenceZone = JDK_116_REFERENCE_LIST[i];
155             ZoneDescriptor currentZone = hash.get(referenceZone.getID());
156             if (referenceZone.equals(currentZone)) {
157                 logln("ok " + referenceZone);
158             }
159             else {
160                 errln("Fail: Expected " + referenceZone +
161                       "; got " + currentZone);
162             }
163         }
164     }
165 
166     /**
167      * A descriptor for a zone; used to regress the short zone IDs.
168      */
169     static class ZoneDescriptor {
170         String id;
171         int offset; // In minutes
172         boolean daylight;
173 
174         ZoneDescriptor(TimeZone zone) {
175             this.id = zone.getID();
176             this.offset = zone.getRawOffset() / 60000;
177             this.daylight = zone.useDaylightTime();
178         }
179 
180         ZoneDescriptor(String id, int offset, boolean daylight) {

224     static final String formatSeconds(int sec) {
225         char sign = '+';
226         if (sec < 0) { sign = '-'; sec = -sec; }
227         int h = sec / 3_600;
228         int m = sec % 3_600 / 60;
229         sec = sec % 60;
230         return "" + sign + h + ":" + ((m<10) ? "0" : "") + m +
231                 (sec > 0 ? ":" + ((sec < 10) ? "0" : "") + sec : "");
232     }
233     /**
234      * As part of the VM fix (see CCC approved RFE 4028006, bug
235      * 4044013), TimeZone.getTimeZone() has been modified to recognize
236      * generic IDs of the form GMT[+-]hh:mm, GMT[+-]hhmm, and
237      * GMT[+-]hh.  Test this behavior here.
238      *
239      * Bug 4044013
240      *
241      * ID "Custom" is no longer used for TimeZone objects created with
242      * a custom time zone ID, such as "GMT-8". See 4322313.
243      */

244     public void TestCustomParse() throws Exception {
245         Object[] DATA = {
246             // ID               Expected offset in seconds
247             "GMT",              null,
248             "GMT+0",            0,
249             "GMT+1",            60 * 60,
250             "GMT-0030",         -30 * 60,
251             "GMT+15:99",        null,
252             "GMT+",             null,
253             "GMT-",             null,
254             "GMT+0:",           null,
255             "GMT-:",            null,
256             "GMT+0010",         10 * 60, // Interpret this as 00:10
257             "GMT-10",           -10 * 60 * 60,
258             "GMT+30",           null,
259             "GMT-3:30",         -(3 * 60 + 30) * 60,
260             "GMT-230",          -(2 * 60 + 30) * 60,
261             "GMT+00:00:01",     1,
262             "GMT-00:00:01",     -1,
263             "GMT+00000",        null,
264             "GMT+00:00:01:",    null,
265             "GMT+00:00:012",    null,
266             "GMT+00:00:0",      null,
267             "GMT+00:00:",       null,
268         };
269         for (int i=0; i<DATA.length; i+=2) {
270             String id = (String)DATA[i];
271             Integer exp = (Integer)DATA[i+1];
272             TimeZone zone = TimeZone.getTimeZone(id);
273             if (zone.getID().equals("GMT")) {
274                 logln(id + " -> generic GMT");
275                 // When TimeZone.getTimeZone() can't parse the id, it
276                 // returns GMT -- a dubious practice, but required for
277                 // backward compatibility.
278                 if (exp != null) {
279                     throw new Exception("Expected offset of " + formatSeconds(exp.intValue()) +
280                                         " for " + id + ", got parse failure");
281                 }
282             }
283             else {
284                 int ioffset = zone.getRawOffset() / 1_000;
285                 String offset = formatSeconds(ioffset);
286                 logln(id + " -> " + zone.getID() + " GMT" + offset);
287                 if (exp == null) {
288                     throw new Exception("Expected parse failure for " + id +
289                                         ", got offset of " + offset +
290                                         ", id " + zone.getID());
291                 }
292                 else if (ioffset != exp.intValue()) {
293                     throw new Exception("Expected offset of " + formatSeconds(exp.intValue()) +
294                                         ", id Custom, for " + id +
295                                         ", got offset of " + offset +
296                                         ", id " + zone.getID());
297                 }
298             }
299         }
300     }
301 
302     /**
303      * Test the basic functionality of the getDisplayName() API.
304      *
305      * Bug 4112869
306      * Bug 4028006
307      *
308      * See also API change request A41.
309      *
310      * 4/21/98 - make smarter, so the test works if the ext resources
311      * are present or not.
312      */

313     public void TestDisplayName() {
314         TimeZone zone = TimeZone.getTimeZone("PST");
315         String name = zone.getDisplayName(Locale.ENGLISH);
316         logln("PST->" + name);
317         if (!name.equals("Pacific Standard Time"))
318             errln("Fail: Expected \"Pacific Standard Time\"");
319 
320         //*****************************************************************
321         // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES
322         // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES
323         // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES
324         //*****************************************************************
325         Object[] DATA = {
326             new Boolean(false), new Integer(TimeZone.SHORT), "PST",
327             new Boolean(true),  new Integer(TimeZone.SHORT), "PDT",
328             new Boolean(false), new Integer(TimeZone.LONG),  "Pacific Standard Time",
329             new Boolean(true),  new Integer(TimeZone.LONG),  "Pacific Daylight Time",
330         };
331 
332         for (int i=0; i<DATA.length; i+=3) {
333             name = zone.getDisplayName(((Boolean)DATA[i]).booleanValue(),
334                                        ((Integer)DATA[i+1]).intValue(),
335                                        Locale.ENGLISH);
336             if (!name.equals(DATA[i+2]))
337                 errln("Fail: Expected " + DATA[i+2] + "; got " + name);
338         }
339 
340         // Make sure that we don't display the DST name by constructing a fake
341         // PST zone that has DST all year long.
342         SimpleTimeZone zone2 = new SimpleTimeZone(0, "PST");
343         zone2.setStartRule(Calendar.JANUARY, 1, 0);
344         zone2.setEndRule(Calendar.DECEMBER, 31, 0);
345         logln("Modified PST inDaylightTime->" + zone2.inDaylightTime(new Date()));
346         name = zone2.getDisplayName(Locale.ENGLISH);
347         logln("Modified PST->" + name);
348         if (!name.equals("Pacific Standard Time"))
349             errln("Fail: Expected \"Pacific Standard Time\"");
350 
351         // Make sure we get the default display format for Locales
352         // with no display name data.
353         Locale zh_CN = Locale.SIMPLIFIED_CHINESE;
354         name = zone.getDisplayName(zh_CN);
355         //*****************************************************************
356         // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES
357         // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES
358         // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES
359         //*****************************************************************
360         logln("PST(zh_CN)->" + name);
361 
362         // Now be smart -- check to see if zh resource is even present.
363         // If not, we expect the en fallback behavior.
364         ResourceBundle enRB = LocaleData.getBundle("sun.util.resources.TimeZoneNames",
365                                                    Locale.ENGLISH);
366         ResourceBundle zhRB = LocaleData.getBundle("sun.util.resources.TimeZoneNames",
367                                                    zh_CN);
368 
369         boolean noZH = enRB == zhRB;
370 
371         if (noZH) {
372             logln("Warning: Not testing the zh_CN behavior because resource is absent");
373             if (!name.equals("Pacific Standard Time"))
374                 errln("Fail: Expected Pacific Standard Time");
375         }
376         else if (!name.equals("Pacific Standard Time") &&
377                  !name.equals("\u592a\u5e73\u6d0b\u6807\u51c6\u65f6\u95f4") &&
378                  !name.equals("\u5317\u7f8e\u592a\u5e73\u6d0b\u6807\u51c6\u65f6\u95f4") &&
379                  !name.equals("GMT-08:00") &&
380                  !name.equals("GMT-8:00") &&
381                  !name.equals("GMT-0800") &&
382                  !name.equals("GMT-800")) {
383             errln("Fail: Expected GMT-08:00 or something similar");
384             errln("************************************************************");
385             errln("THE ABOVE FAILURE MAY JUST MEAN THE LOCALE DATA HAS CHANGED");
386             errln("************************************************************");
387         }
388 
389         // Now try a non-existent zone
390         zone2 = new SimpleTimeZone(90*60*1000, "xyzzy");
391         name = zone2.getDisplayName(Locale.ENGLISH);
392         logln("GMT+90min->" + name);
393         if (!name.equals("GMT+01:30") &&
394             !name.equals("GMT+1:30") &&
395             !name.equals("GMT+0130") &&
396             !name.equals("GMT+130"))
397             errln("Fail: Expected GMT+01:30 or something similar");
398     }
399 

400     public void TestGenericAPI() {
401         String id = "NewGMT";
402         int offset = 12345;
403 
404         SimpleTimeZone zone = new SimpleTimeZone(offset, id);
405         if (zone.useDaylightTime()) {
406             errln("FAIL: useDaylightTime should return false");
407         }
408 
409         TimeZone zoneclone = (TimeZone)zone.clone();
410         if (!zoneclone.equals(zone)) {
411             errln("FAIL: clone or operator== failed");
412         }
413         zoneclone.setID("abc");
414         if (zoneclone.equals(zone)) {
415             errln("FAIL: clone or operator!= failed");
416         }
417 
418         zoneclone = (TimeZone)zone.clone();
419         if (!zoneclone.equals(zone)) {
420             errln("FAIL: clone or operator== failed");
421         }
422         zoneclone.setRawOffset(45678);
423         if (zoneclone.equals(zone)) {
424             errln("FAIL: clone or operator!= failed");
425         }
426 
427         TimeZone saveDefault = TimeZone.getDefault();
428         try {
429             TimeZone.setDefault(zone);
430             TimeZone defaultzone = TimeZone.getDefault();
431             if (defaultzone == zone) {
432                 errln("FAIL: Default object is identical, not clone");
433             }
434             if (!defaultzone.equals(zone)) {
435                 errln("FAIL: Default object is not equal");
436             }
437         }
438         finally {
439             TimeZone.setDefault(saveDefault);
440         }
441     }
442 
443     @SuppressWarnings("deprecation")

444     public void TestRuleAPI()
445     {
446         // ErrorCode status = ZERO_ERROR;
447 
448         int offset = (int)(60*60*1000*1.75); // Pick a weird offset
449         SimpleTimeZone zone = new SimpleTimeZone(offset, "TestZone");
450         if (zone.useDaylightTime()) errln("FAIL: useDaylightTime should return false");
451 
452         // Establish our expected transition times.  Do this with a non-DST
453         // calendar with the (above) declared local offset.
454         GregorianCalendar gc = new GregorianCalendar(zone);
455         gc.clear();
456         gc.set(1990, Calendar.MARCH, 1);
457         long marchOneStd = gc.getTime().getTime(); // Local Std time midnight
458         gc.clear();
459         gc.set(1990, Calendar.JULY, 1);
460         long julyOneStd = gc.getTime().getTime(); // Local Std time midnight
461 
462         // Starting and ending hours, WALL TIME
463         int startHour = (int)(2.25 * 3600000);
464         int endHour   = (int)(3.5  * 3600000);
465 
466         zone.setStartRule(Calendar.MARCH, 1, 0, startHour);
467         zone.setEndRule  (Calendar.JULY,  1, 0, endHour);
468 
469         gc = new GregorianCalendar(zone);
470         // if (failure(status, "new GregorianCalendar")) return;
471 
472         long marchOne = marchOneStd + startHour;
473         long julyOne = julyOneStd + endHour - 3600000; // Adjust from wall to Std time
474 
475         long expMarchOne = 636251400000L;
476         if (marchOne != expMarchOne)
477         {
478             errln("FAIL: Expected start computed as " + marchOne +
479                   " = " + new Date(marchOne));
480             logln("      Should be                  " + expMarchOne +
481                   " = " + new Date(expMarchOne));
482         }
483 
484         long expJulyOne = 646793100000L;
485         if (julyOne != expJulyOne)
486         {
487             errln("FAIL: Expected start computed as " + julyOne +
488                   " = " + new Date(julyOne));
489             logln("      Should be                  " + expJulyOne +
490                   " = " + new Date(expJulyOne));
491         }
492 
493         testUsingBinarySearch(zone, new Date(90, Calendar.JANUARY, 1).getTime(),
494                               new Date(90, Calendar.JUNE, 15).getTime(), marchOne);
495         testUsingBinarySearch(zone, new Date(90, Calendar.JUNE, 1).getTime(),
496                               new Date(90, Calendar.DECEMBER, 31).getTime(), julyOne);
497 
498         if (zone.inDaylightTime(new Date(marchOne - 1000)) ||
499             !zone.inDaylightTime(new Date(marchOne)))
500             errln("FAIL: Start rule broken");
501         if (!zone.inDaylightTime(new Date(julyOne - 1000)) ||
502             zone.inDaylightTime(new Date(julyOne)))
503             errln("FAIL: End rule broken");
504 
505         zone.setStartYear(1991);
506         if (zone.inDaylightTime(new Date(marchOne)) ||
507             zone.inDaylightTime(new Date(julyOne - 1000)))
508             errln("FAIL: Start year broken");
509 
510         // failure(status, "TestRuleAPI");
511         // delete gc;
512         // delete zone;
513     }
514 
515     void testUsingBinarySearch(SimpleTimeZone tz, long min, long max, long expectedBoundary)
516     {
517         // ErrorCode status = ZERO_ERROR;
518         boolean startsInDST = tz.inDaylightTime(new Date(min));
519         // if (failure(status, "SimpleTimeZone::inDaylightTime")) return;
520         if (tz.inDaylightTime(new Date(max)) == startsInDST) {
521             logln("Error: inDaylightTime(" + new Date(max) + ") != " + (!startsInDST));
522             return;
523         }
524         // if (failure(status, "SimpleTimeZone::inDaylightTime")) return;
525         while ((max - min) > INTERVAL) {
526             long mid = (min + max) / 2;
527             if (tz.inDaylightTime(new Date(mid)) == startsInDST) {
528                 min = mid;
529             }
530             else {
531                 max = mid;
532             }
533             // if (failure(status, "SimpleTimeZone::inDaylightTime")) return;
534         }
535         logln("Binary Search Before: " + min + " = " + new Date(min));
536         logln("Binary Search After:  " + max + " = " + new Date(max));
537         long mindelta = expectedBoundary - min;
538         long maxdelta = max - expectedBoundary;
539         if (mindelta >= 0 &&
540             mindelta <= INTERVAL &&
541             mindelta >= 0 &&
542             mindelta <= INTERVAL)
543             logln("PASS: Expected bdry:  " + expectedBoundary + " = " + new Date(expectedBoundary));
544         else
545             errln("FAIL: Expected bdry:  " + expectedBoundary + " = " + new Date(expectedBoundary));
546     }
547 
548     static final int INTERVAL = 100;
549 
550     // Bug 006; verify the offset for a specific zone.

551     public void TestPRTOffset()
552     {
553         TimeZone tz = TimeZone.getTimeZone( "PRT" );
554         if( tz == null ) {
555             errln( "FAIL: TimeZone(PRT) is null" );
556         }
557         else{
558             if (tz.getRawOffset() != (-4*millisPerHour))
559                 errln("FAIL: Offset for PRT should be -4");
560         }
561 
562     }
563 
564     // Test various calls
565     @SuppressWarnings("deprecation")

566     public void TestVariousAPI518()
567     {
568         TimeZone time_zone = TimeZone.getTimeZone("PST");
569         Date d = new Date(97, Calendar.APRIL, 30);
570 
571         logln("The timezone is " + time_zone.getID());
572 
573         if (time_zone.inDaylightTime(d) != true)
574             errln("FAIL: inDaylightTime returned false");
575 
576         if (time_zone.useDaylightTime() != true)
577             errln("FAIL: useDaylightTime returned false");
578 
579         if (time_zone.getRawOffset() != -8*millisPerHour)
580             errln( "FAIL: getRawOffset returned wrong value");
581 
582         GregorianCalendar gc = new GregorianCalendar();
583         gc.setTime(d);
584         if (time_zone.getOffset(gc.AD, gc.get(gc.YEAR), gc.get(gc.MONTH),
585                                 gc.get(gc.DAY_OF_MONTH),
586                                 gc.get(gc.DAY_OF_WEEK), 0)
587             != -7*millisPerHour)
588             errln("FAIL: getOffset returned wrong value");
589     }
590 
591     // Test getAvailableID API

592     public void TestGetAvailableIDs913()
593     {
594         StringBuffer buf = new StringBuffer("TimeZone.getAvailableIDs() = { ");
595         String[] s = TimeZone.getAvailableIDs();
596         for (int i=0; i<s.length; ++i)
597         {
598             if (i > 0) buf.append(", ");
599             buf.append(s[i]);
600         }
601         buf.append(" };");
602         logln(buf.toString());
603 
604         buf.setLength(0);
605         buf.append("TimeZone.getAvailableIDs(GMT+02:00) = { ");
606         s = TimeZone.getAvailableIDs(+2 * 60 * 60 * 1000);
607         for (int i=0; i<s.length; ++i)
608         {
609             if (i > 0) buf.append(", ");
610             buf.append(s[i]);
611         }
612         buf.append(" };");
613         logln(buf.toString());
614 
615         TimeZone tz = TimeZone.getTimeZone("PST");
616         if (tz != null)
617             logln("getTimeZone(PST) = " + tz.getID());
618         else
619             errln("FAIL: getTimeZone(PST) = null");
620 
621         tz = TimeZone.getTimeZone("America/Los_Angeles");
622         if (tz != null)
623             logln("getTimeZone(America/Los_Angeles) = " + tz.getID());
624         else
625             errln("FAIL: getTimeZone(PST) = null");
626 
627         // Bug 4096694
628         tz = TimeZone.getTimeZone("NON_EXISTENT");
629         if (tz == null)
630             errln("FAIL: getTimeZone(NON_EXISTENT) = null");
631         else if (!tz.getID().equals("GMT"))
632             errln("FAIL: getTimeZone(NON_EXISTENT) = " + tz.getID());
633     }
634 
635     /**
636      * Bug 4107276
637      */

638     public void TestDSTSavings() {
639         // It might be better to find a way to integrate this test into the main TimeZone
640         // tests above, but I don't have time to figure out how to do this (or if it's
641         // even really a good idea).  Let's consider that a future.  --rtg 1/27/98
642         SimpleTimeZone tz = new SimpleTimeZone(-5 * millisPerHour, "dstSavingsTest",
643                                                Calendar.MARCH, 1, 0, 0, Calendar.SEPTEMBER, 1, 0, 0,
644                                                (int)(0.5 * millisPerHour));
645 
646         if (tz.getRawOffset() != -5 * millisPerHour)
647             errln("Got back a raw offset of " + (tz.getRawOffset() / millisPerHour) +
648                   " hours instead of -5 hours.");
649         if (!tz.useDaylightTime())
650             errln("Test time zone should use DST but claims it doesn't.");
651         if (tz.getDSTSavings() != 0.5 * millisPerHour)
652             errln("Set DST offset to 0.5 hour, but got back " + (tz.getDSTSavings() /
653                                                                  millisPerHour) + " hours instead.");
654 
655         int offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JANUARY, 1,
656                                   Calendar.THURSDAY, 10 * millisPerHour);
657         if (offset != -5 * millisPerHour)
658             errln("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got "
659                   + (offset / millisPerHour) + " hours.");
660 
661         offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JUNE, 1, Calendar.MONDAY,
662                               10 * millisPerHour);
663         if (offset != -4.5 * millisPerHour)
664             errln("The offset for 10 AM, 6/1/98 should have been -4.5 hours, but we got "
665                   + (offset / millisPerHour) + " hours.");
666 
667         tz.setDSTSavings(millisPerHour);
668         offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JANUARY, 1,
669                               Calendar.THURSDAY, 10 * millisPerHour);
670         if (offset != -5 * millisPerHour)
671             errln("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got "
672                   + (offset / millisPerHour) + " hours.");
673 
674         offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JUNE, 1, Calendar.MONDAY,
675                               10 * millisPerHour);
676         if (offset != -4 * millisPerHour)
677             errln("The offset for 10 AM, 6/1/98 (with a 1-hour DST offset) should have been -4 hours, but we got "
678                   + (offset / millisPerHour) + " hours.");
679     }
680 
681     /**
682      * Bug 4107570
683      */

684     public void TestAlternateRules() {
685         // Like TestDSTSavings, this test should probably be integrated somehow with the main
686         // test at the top of this class, but I didn't have time to figure out how to do that.
687         //                      --rtg 1/28/98
688 
689         SimpleTimeZone tz = new SimpleTimeZone(-5 * millisPerHour, "alternateRuleTest");
690 
691         // test the day-of-month API
692         tz.setStartRule(Calendar.MARCH, 10, 12 * millisPerHour);
693         tz.setEndRule(Calendar.OCTOBER, 20, 12 * millisPerHour);
694 
695         int offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 5,
696                                   Calendar.THURSDAY, 10 * millisPerHour);
697         if (offset != -5 * millisPerHour)
698             errln("The offset for 10AM, 3/5/98 should have been -5 hours, but we got "
699                   + (offset / millisPerHour) + " hours.");
700 
701         offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 15,
702                               Calendar.SUNDAY, 10 * millisPerHour);
703         if (offset != -4 * millisPerHour)
704             errln("The offset for 10AM, 3/15/98 should have been -4 hours, but we got "
705                   + (offset / millisPerHour) + " hours.");
706 
707         offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 15,
708                               Calendar.THURSDAY, 10 * millisPerHour);
709         if (offset != -4 * millisPerHour)
710             errln("The offset for 10AM, 10/15/98 should have been -4 hours, but we got "
711                   + (offset / millisPerHour) + " hours.");
712 
713         offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 25,
714                               Calendar.SUNDAY, 10 * millisPerHour);
715         if (offset != -5 * millisPerHour)
716             errln("The offset for 10AM, 10/25/98 should have been -5 hours, but we got "
717                   + (offset / millisPerHour) + " hours.");
718 
719         // test the day-of-week-after-day-in-month API
720         tz.setStartRule(Calendar.MARCH, 10, Calendar.FRIDAY, 12 * millisPerHour, true);
721         tz.setEndRule(Calendar.OCTOBER, 20, Calendar.FRIDAY, 12 * millisPerHour, false);
722 
723         offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 11,
724                               Calendar.WEDNESDAY, 10 * millisPerHour);
725         if (offset != -5 * millisPerHour)
726             errln("The offset for 10AM, 3/11/98 should have been -5 hours, but we got "
727                   + (offset / millisPerHour) + " hours.");
728 
729         offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 14,
730                               Calendar.SATURDAY, 10 * millisPerHour);
731         if (offset != -4 * millisPerHour)
732             errln("The offset for 10AM, 3/14/98 should have been -4 hours, but we got "
733                   + (offset / millisPerHour) + " hours.");
734 
735         offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 15,
736                               Calendar.THURSDAY, 10 * millisPerHour);
737         if (offset != -4 * millisPerHour)
738             errln("The offset for 10AM, 10/15/98 should have been -4 hours, but we got "
739                   + (offset / millisPerHour) + " hours.");
740 
741         offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 17,
742                               Calendar.SATURDAY, 10 * millisPerHour);
743         if (offset != -5 * millisPerHour)
744             errln("The offset for 10AM, 10/17/98 should have been -5 hours, but we got "
745                   + (offset / millisPerHour) + " hours.");
746     }
747 }
748 
749 //eof

 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 /*
 25  * @test
 26  * @bug 4028006 4044013 4096694 4107276 4107570 4112869 4130885 7039469 7126465 7158483
 27  *      8008577 8077685 8098547 8133321 8138716 8148446 8151876 8159684 8166875 8181157
 28  *      8228469 8274407 8285844 8305113
 29  * @modules java.base/sun.util.resources

 30  * @summary test TimeZone
 31  * @run junit TimeZoneTest
 32  */
 33 
 34 import java.io.*;
 35 import java.text.*;
 36 import java.util.*;
 37 import sun.util.resources.LocaleData;
 38 
 39 import org.junit.jupiter.api.Test;
 40 
 41 import static org.junit.jupiter.api.Assertions.fail;
 42 
 43 public class TimeZoneTest
 44 {
 45     static final int millisPerHour = 3600000;
 46 




 47     /**
 48      * Bug 4130885
 49      * Certain short zone IDs, used since 1.1.x, are incorrect.
 50      *
 51      * The worst of these is:
 52      *
 53      * "CAT" (Central African Time) should be GMT+2:00, but instead returns a
 54      * zone at GMT-1:00. The zone at GMT-1:00 should be called EGT, CVT, EGST,
 55      * or AZOST, depending on which zone is meant, but in no case is it CAT.
 56      *
 57      * Other wrong zone IDs:
 58      *
 59      * ECT (European Central Time) GMT+1:00: ECT is Ecuador Time,
 60      * GMT-5:00. European Central time is abbreviated CEST.
 61      *
 62      * SST (Solomon Island Time) GMT+11:00. SST is actually Samoa Standard Time,
 63      * GMT-11:00. Solomon Island time is SBT.
 64      *
 65      * NST (New Zealand Time) GMT+12:00. NST is the abbreviation for
 66      * Newfoundland Standard Time, GMT-3:30. New Zealanders use NZST.

 82      * ART (should be EET)
 83      * MET (should be IRST)
 84      * NET (should be AMST)
 85      * PLT (should be PKT)
 86      * BST (should be BDT)
 87      * VST (should be ICT)
 88      * CTT (should be CST) +
 89      * ACT (should be CST) +
 90      * AET (should be EST) +
 91      * MIT (should be WST) +
 92      * IET (should be EST) +
 93      * PRT (should be AST) +
 94      * CNT (should be NST)
 95      * AGT (should be ARST)
 96      * BET (should be EST) +
 97      *
 98      * + A zone with the correct name already exists and means something
 99      * else. E.g., EST usually indicates the US Eastern zone, so it cannot be
100      * used for Brazil (BET).
101      */
102     @Test
103     public void TestShortZoneIDs() throws Exception {
104 
105         ZoneDescriptor[] JDK_116_REFERENCE_LIST = {
106             new ZoneDescriptor("MIT", 780, false), // Samoa no longer observes DST starting 2021b
107             new ZoneDescriptor("HST", -600, false),
108             new ZoneDescriptor("AST", -540, true),
109             new ZoneDescriptor("PST", -480, true),
110             new ZoneDescriptor("PNT", -420, false),
111             new ZoneDescriptor("MST", -420, false),
112             new ZoneDescriptor("CST", -360, true),
113             new ZoneDescriptor("IET", -300, true),
114             new ZoneDescriptor("EST", -300, false),
115             new ZoneDescriptor("PRT", -240, false),
116             new ZoneDescriptor("CNT", -210, true),
117             new ZoneDescriptor("AGT", -180, false),
118             new ZoneDescriptor("BET", -180, false),
119             // new ZoneDescriptor("CAT", -60, false), // Wrong:
120             // As of bug 4130885, fix CAT (Central Africa)
121             new ZoneDescriptor("CAT", 120, false), // Africa/Harare
122             new ZoneDescriptor("GMT", 0, false),

137             new ZoneDescriptor("AET", 600, true),
138             new ZoneDescriptor("SST", 660, false),
139             // new ZoneDescriptor("NST", 720, false),
140             // As of bug 4130885, fix NST (New Zealand)
141             new ZoneDescriptor("NST", 720, true), // Pacific/Auckland
142         };
143 
144         Map<String, ZoneDescriptor> hash = new HashMap<>();
145 
146         String[] ids = TimeZone.getAvailableIDs();
147         for (String id : ids) {
148             if (id.length() == 3) {
149                 hash.put(id, new ZoneDescriptor(TimeZone.getTimeZone(id)));
150             }
151         }
152 
153         for (int i = 0; i < JDK_116_REFERENCE_LIST.length; ++i) {
154             ZoneDescriptor referenceZone = JDK_116_REFERENCE_LIST[i];
155             ZoneDescriptor currentZone = hash.get(referenceZone.getID());
156             if (referenceZone.equals(currentZone)) {
157                 System.out.println("ok " + referenceZone);
158             }
159             else {
160                 fail("Fail: Expected " + referenceZone +
161                       "; got " + currentZone);
162             }
163         }
164     }
165 
166     /**
167      * A descriptor for a zone; used to regress the short zone IDs.
168      */
169     static class ZoneDescriptor {
170         String id;
171         int offset; // In minutes
172         boolean daylight;
173 
174         ZoneDescriptor(TimeZone zone) {
175             this.id = zone.getID();
176             this.offset = zone.getRawOffset() / 60000;
177             this.daylight = zone.useDaylightTime();
178         }
179 
180         ZoneDescriptor(String id, int offset, boolean daylight) {

224     static final String formatSeconds(int sec) {
225         char sign = '+';
226         if (sec < 0) { sign = '-'; sec = -sec; }
227         int h = sec / 3_600;
228         int m = sec % 3_600 / 60;
229         sec = sec % 60;
230         return "" + sign + h + ":" + ((m<10) ? "0" : "") + m +
231                 (sec > 0 ? ":" + ((sec < 10) ? "0" : "") + sec : "");
232     }
233     /**
234      * As part of the VM fix (see CCC approved RFE 4028006, bug
235      * 4044013), TimeZone.getTimeZone() has been modified to recognize
236      * generic IDs of the form GMT[+-]hh:mm, GMT[+-]hhmm, and
237      * GMT[+-]hh.  Test this behavior here.
238      *
239      * Bug 4044013
240      *
241      * ID "Custom" is no longer used for TimeZone objects created with
242      * a custom time zone ID, such as "GMT-8". See 4322313.
243      */
244     @Test
245     public void TestCustomParse() throws Exception {
246         Object[] DATA = {
247             // ID               Expected offset in seconds
248             "GMT",              null,
249             "GMT+0",            0,
250             "GMT+1",            60 * 60,
251             "GMT-0030",         -30 * 60,
252             "GMT+15:99",        null,
253             "GMT+",             null,
254             "GMT-",             null,
255             "GMT+0:",           null,
256             "GMT-:",            null,
257             "GMT+0010",         10 * 60, // Interpret this as 00:10
258             "GMT-10",           -10 * 60 * 60,
259             "GMT+30",           null,
260             "GMT-3:30",         -(3 * 60 + 30) * 60,
261             "GMT-230",          -(2 * 60 + 30) * 60,
262             "GMT+00:00:01",     1,
263             "GMT-00:00:01",     -1,
264             "GMT+00000",        null,
265             "GMT+00:00:01:",    null,
266             "GMT+00:00:012",    null,
267             "GMT+00:00:0",      null,
268             "GMT+00:00:",       null,
269         };
270         for (int i=0; i<DATA.length; i+=2) {
271             String id = (String)DATA[i];
272             Integer exp = (Integer)DATA[i+1];
273             TimeZone zone = TimeZone.getTimeZone(id);
274             if (zone.getID().equals("GMT")) {
275                 System.out.println(id + " -> generic GMT");
276                 // When TimeZone.getTimeZone() can't parse the id, it
277                 // returns GMT -- a dubious practice, but required for
278                 // backward compatibility.
279                 if (exp != null) {
280                     throw new Exception("Expected offset of " + formatSeconds(exp.intValue()) +
281                                         " for " + id + ", got parse failure");
282                 }
283             }
284             else {
285                 int ioffset = zone.getRawOffset() / 1_000;
286                 String offset = formatSeconds(ioffset);
287                 System.out.println(id + " -> " + zone.getID() + " GMT" + offset);
288                 if (exp == null) {
289                     throw new Exception("Expected parse failure for " + id +
290                                         ", got offset of " + offset +
291                                         ", id " + zone.getID());
292                 }
293                 else if (ioffset != exp.intValue()) {
294                     throw new Exception("Expected offset of " + formatSeconds(exp.intValue()) +
295                                         ", id Custom, for " + id +
296                                         ", got offset of " + offset +
297                                         ", id " + zone.getID());
298                 }
299             }
300         }
301     }
302 
303     /**
304      * Test the basic functionality of the getDisplayName() API.
305      *
306      * Bug 4112869
307      * Bug 4028006
308      *
309      * See also API change request A41.
310      *
311      * 4/21/98 - make smarter, so the test works if the ext resources
312      * are present or not.
313      */
314     @Test
315     public void TestDisplayName() {
316         TimeZone zone = TimeZone.getTimeZone("PST");
317         String name = zone.getDisplayName(Locale.ENGLISH);
318         System.out.println("PST->" + name);
319         if (!name.equals("Pacific Standard Time"))
320             fail("Fail: Expected \"Pacific Standard Time\"");
321 
322         //*****************************************************************
323         // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES
324         // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES
325         // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES
326         //*****************************************************************
327         Object[] DATA = {
328             new Boolean(false), new Integer(TimeZone.SHORT), "PST",
329             new Boolean(true),  new Integer(TimeZone.SHORT), "PDT",
330             new Boolean(false), new Integer(TimeZone.LONG),  "Pacific Standard Time",
331             new Boolean(true),  new Integer(TimeZone.LONG),  "Pacific Daylight Time",
332         };
333 
334         for (int i=0; i<DATA.length; i+=3) {
335             name = zone.getDisplayName(((Boolean)DATA[i]).booleanValue(),
336                                        ((Integer)DATA[i+1]).intValue(),
337                                        Locale.ENGLISH);
338             if (!name.equals(DATA[i+2]))
339                 fail("Fail: Expected " + DATA[i+2] + "; got " + name);
340         }
341 
342         // Make sure that we don't display the DST name by constructing a fake
343         // PST zone that has DST all year long.
344         SimpleTimeZone zone2 = new SimpleTimeZone(0, "PST");
345         zone2.setStartRule(Calendar.JANUARY, 1, 0);
346         zone2.setEndRule(Calendar.DECEMBER, 31, 0);
347         System.out.println("Modified PST inDaylightTime->" + zone2.inDaylightTime(new Date()));
348         name = zone2.getDisplayName(Locale.ENGLISH);
349         System.out.println("Modified PST->" + name);
350         if (!name.equals("Pacific Standard Time"))
351             fail("Fail: Expected \"Pacific Standard Time\"");
352 
353         // Make sure we get the default display format for Locales
354         // with no display name data.
355         Locale zh_CN = Locale.SIMPLIFIED_CHINESE;
356         name = zone.getDisplayName(zh_CN);
357         //*****************************************************************
358         // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES
359         // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES
360         // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES
361         //*****************************************************************
362         System.out.println("PST(zh_CN)->" + name);
363 
364         // Now be smart -- check to see if zh resource is even present.
365         // If not, we expect the en fallback behavior.
366         ResourceBundle enRB = LocaleData.getBundle("sun.util.resources.TimeZoneNames",
367                                                    Locale.ENGLISH);
368         ResourceBundle zhRB = LocaleData.getBundle("sun.util.resources.TimeZoneNames",
369                                                    zh_CN);
370 
371         boolean noZH = enRB == zhRB;
372 
373         if (noZH) {
374             System.out.println("Warning: Not testing the zh_CN behavior because resource is absent");
375             if (!name.equals("Pacific Standard Time"))
376                 fail("Fail: Expected Pacific Standard Time");
377         }
378         else if (!name.equals("Pacific Standard Time") &&
379                  !name.equals("\u592a\u5e73\u6d0b\u6807\u51c6\u65f6\u95f4") &&
380                  !name.equals("\u5317\u7f8e\u592a\u5e73\u6d0b\u6807\u51c6\u65f6\u95f4") &&
381                  !name.equals("GMT-08:00") &&
382                  !name.equals("GMT-8:00") &&
383                  !name.equals("GMT-0800") &&
384                  !name.equals("GMT-800")) {
385             fail("Fail: Expected GMT-08:00 or something similar\n"
386             + "************************************************************\n"
387             + "THE ABOVE FAILURE MAY JUST MEAN THE LOCALE DATA HAS CHANGED\n"
388             + "************************************************************\n");
389         }
390 
391         // Now try a non-existent zone
392         zone2 = new SimpleTimeZone(90*60*1000, "xyzzy");
393         name = zone2.getDisplayName(Locale.ENGLISH);
394         System.out.println("GMT+90min->" + name);
395         if (!name.equals("GMT+01:30") &&
396             !name.equals("GMT+1:30") &&
397             !name.equals("GMT+0130") &&
398             !name.equals("GMT+130"))
399             fail("Fail: Expected GMT+01:30 or something similar");
400     }
401 
402     @Test
403     public void TestGenericAPI() {
404         String id = "NewGMT";
405         int offset = 12345;
406 
407         SimpleTimeZone zone = new SimpleTimeZone(offset, id);
408         if (zone.useDaylightTime()) {
409             fail("FAIL: useDaylightTime should return false");
410         }
411 
412         TimeZone zoneclone = (TimeZone)zone.clone();
413         if (!zoneclone.equals(zone)) {
414             fail("FAIL: clone or operator== failed");
415         }
416         zoneclone.setID("abc");
417         if (zoneclone.equals(zone)) {
418             fail("FAIL: clone or operator!= failed");
419         }
420 
421         zoneclone = (TimeZone)zone.clone();
422         if (!zoneclone.equals(zone)) {
423             fail("FAIL: clone or operator== failed");
424         }
425         zoneclone.setRawOffset(45678);
426         if (zoneclone.equals(zone)) {
427             fail("FAIL: clone or operator!= failed");
428         }
429 
430         TimeZone saveDefault = TimeZone.getDefault();
431         try {
432             TimeZone.setDefault(zone);
433             TimeZone defaultzone = TimeZone.getDefault();
434             if (defaultzone == zone) {
435                 fail("FAIL: Default object is identical, not clone");
436             }
437             if (!defaultzone.equals(zone)) {
438                 fail("FAIL: Default object is not equal");
439             }
440         }
441         finally {
442             TimeZone.setDefault(saveDefault);
443         }
444     }
445 
446     @SuppressWarnings("deprecation")
447     @Test
448     public void TestRuleAPI()
449     {
450         // ErrorCode status = ZERO_ERROR;
451 
452         int offset = (int)(60*60*1000*1.75); // Pick a weird offset
453         SimpleTimeZone zone = new SimpleTimeZone(offset, "TestZone");
454         if (zone.useDaylightTime()) fail("FAIL: useDaylightTime should return false");
455 
456         // Establish our expected transition times.  Do this with a non-DST
457         // calendar with the (above) declared local offset.
458         GregorianCalendar gc = new GregorianCalendar(zone);
459         gc.clear();
460         gc.set(1990, Calendar.MARCH, 1);
461         long marchOneStd = gc.getTime().getTime(); // Local Std time midnight
462         gc.clear();
463         gc.set(1990, Calendar.JULY, 1);
464         long julyOneStd = gc.getTime().getTime(); // Local Std time midnight
465 
466         // Starting and ending hours, WALL TIME
467         int startHour = (int)(2.25 * 3600000);
468         int endHour   = (int)(3.5  * 3600000);
469 
470         zone.setStartRule(Calendar.MARCH, 1, 0, startHour);
471         zone.setEndRule  (Calendar.JULY,  1, 0, endHour);
472 
473         gc = new GregorianCalendar(zone);
474         // if (failure(status, "new GregorianCalendar")) return;
475 
476         long marchOne = marchOneStd + startHour;
477         long julyOne = julyOneStd + endHour - 3600000; // Adjust from wall to Std time
478 
479         long expMarchOne = 636251400000L;
480         if (marchOne != expMarchOne)
481         {
482             fail("FAIL: Expected start computed as " + marchOne +
483                   " = " + new Date(marchOne));
484             System.out.println("      Should be                  " + expMarchOne +
485                   " = " + new Date(expMarchOne));
486         }
487 
488         long expJulyOne = 646793100000L;
489         if (julyOne != expJulyOne)
490         {
491             fail("FAIL: Expected start computed as " + julyOne +
492                   " = " + new Date(julyOne));
493             System.out.println("      Should be                  " + expJulyOne +
494                   " = " + new Date(expJulyOne));
495         }
496 
497         testUsingBinarySearch(zone, new Date(90, Calendar.JANUARY, 1).getTime(),
498                               new Date(90, Calendar.JUNE, 15).getTime(), marchOne);
499         testUsingBinarySearch(zone, new Date(90, Calendar.JUNE, 1).getTime(),
500                               new Date(90, Calendar.DECEMBER, 31).getTime(), julyOne);
501 
502         if (zone.inDaylightTime(new Date(marchOne - 1000)) ||
503             !zone.inDaylightTime(new Date(marchOne)))
504             fail("FAIL: Start rule broken");
505         if (!zone.inDaylightTime(new Date(julyOne - 1000)) ||
506             zone.inDaylightTime(new Date(julyOne)))
507             fail("FAIL: End rule broken");
508 
509         zone.setStartYear(1991);
510         if (zone.inDaylightTime(new Date(marchOne)) ||
511             zone.inDaylightTime(new Date(julyOne - 1000)))
512             fail("FAIL: Start year broken");
513 
514         // failure(status, "TestRuleAPI");
515         // delete gc;
516         // delete zone;
517     }
518 
519     void testUsingBinarySearch(SimpleTimeZone tz, long min, long max, long expectedBoundary)
520     {
521         // ErrorCode status = ZERO_ERROR;
522         boolean startsInDST = tz.inDaylightTime(new Date(min));
523         // if (failure(status, "SimpleTimeZone::inDaylightTime")) return;
524         if (tz.inDaylightTime(new Date(max)) == startsInDST) {
525             System.out.println("Error: inDaylightTime(" + new Date(max) + ") != " + (!startsInDST));
526             return;
527         }
528         // if (failure(status, "SimpleTimeZone::inDaylightTime")) return;
529         while ((max - min) > INTERVAL) {
530             long mid = (min + max) / 2;
531             if (tz.inDaylightTime(new Date(mid)) == startsInDST) {
532                 min = mid;
533             }
534             else {
535                 max = mid;
536             }
537             // if (failure(status, "SimpleTimeZone::inDaylightTime")) return;
538         }
539         System.out.println("Binary Search Before: " + min + " = " + new Date(min));
540         System.out.println("Binary Search After:  " + max + " = " + new Date(max));
541         long mindelta = expectedBoundary - min;
542         long maxdelta = max - expectedBoundary;
543         if (mindelta >= 0 &&
544             mindelta <= INTERVAL &&
545             mindelta >= 0 &&
546             mindelta <= INTERVAL)
547             System.out.println("PASS: Expected bdry:  " + expectedBoundary + " = " + new Date(expectedBoundary));
548         else
549             fail("FAIL: Expected bdry:  " + expectedBoundary + " = " + new Date(expectedBoundary));
550     }
551 
552     static final int INTERVAL = 100;
553 
554     // Bug 006; verify the offset for a specific zone.
555     @Test
556     public void TestPRTOffset()
557     {
558         TimeZone tz = TimeZone.getTimeZone( "PRT" );
559         if( tz == null ) {
560             fail( "FAIL: TimeZone(PRT) is null" );
561         }
562         else{
563             if (tz.getRawOffset() != (-4*millisPerHour))
564                 fail("FAIL: Offset for PRT should be -4");
565         }
566 
567     }
568 
569     // Test various calls
570     @SuppressWarnings("deprecation")
571     @Test
572     public void TestVariousAPI518()
573     {
574         TimeZone time_zone = TimeZone.getTimeZone("PST");
575         Date d = new Date(97, Calendar.APRIL, 30);
576 
577         System.out.println("The timezone is " + time_zone.getID());
578 
579         if (time_zone.inDaylightTime(d) != true)
580             fail("FAIL: inDaylightTime returned false");
581 
582         if (time_zone.useDaylightTime() != true)
583             fail("FAIL: useDaylightTime returned false");
584 
585         if (time_zone.getRawOffset() != -8*millisPerHour)
586             fail( "FAIL: getRawOffset returned wrong value");
587 
588         GregorianCalendar gc = new GregorianCalendar();
589         gc.setTime(d);
590         if (time_zone.getOffset(gc.AD, gc.get(gc.YEAR), gc.get(gc.MONTH),
591                                 gc.get(gc.DAY_OF_MONTH),
592                                 gc.get(gc.DAY_OF_WEEK), 0)
593             != -7*millisPerHour)
594             fail("FAIL: getOffset returned wrong value");
595     }
596 
597     // Test getAvailableID API
598     @Test
599     public void TestGetAvailableIDs913()
600     {
601         StringBuffer buf = new StringBuffer("TimeZone.getAvailableIDs() = { ");
602         String[] s = TimeZone.getAvailableIDs();
603         for (int i=0; i<s.length; ++i)
604         {
605             if (i > 0) buf.append(", ");
606             buf.append(s[i]);
607         }
608         buf.append(" };");
609         System.out.println(buf.toString());
610 
611         buf.setLength(0);
612         buf.append("TimeZone.getAvailableIDs(GMT+02:00) = { ");
613         s = TimeZone.getAvailableIDs(+2 * 60 * 60 * 1000);
614         for (int i=0; i<s.length; ++i)
615         {
616             if (i > 0) buf.append(", ");
617             buf.append(s[i]);
618         }
619         buf.append(" };");
620         System.out.println(buf.toString());
621 
622         TimeZone tz = TimeZone.getTimeZone("PST");
623         if (tz != null)
624             System.out.println("getTimeZone(PST) = " + tz.getID());
625         else
626             fail("FAIL: getTimeZone(PST) = null");
627 
628         tz = TimeZone.getTimeZone("America/Los_Angeles");
629         if (tz != null)
630             System.out.println("getTimeZone(America/Los_Angeles) = " + tz.getID());
631         else
632             fail("FAIL: getTimeZone(PST) = null");
633 
634         // Bug 4096694
635         tz = TimeZone.getTimeZone("NON_EXISTENT");
636         if (tz == null)
637             fail("FAIL: getTimeZone(NON_EXISTENT) = null");
638         else if (!tz.getID().equals("GMT"))
639             fail("FAIL: getTimeZone(NON_EXISTENT) = " + tz.getID());
640     }
641 
642     /**
643      * Bug 4107276
644      */
645     @Test
646     public void TestDSTSavings() {
647         // It might be better to find a way to integrate this test into the main TimeZone
648         // tests above, but I don't have time to figure out how to do this (or if it's
649         // even really a good idea).  Let's consider that a future.  --rtg 1/27/98
650         SimpleTimeZone tz = new SimpleTimeZone(-5 * millisPerHour, "dstSavingsTest",
651                                                Calendar.MARCH, 1, 0, 0, Calendar.SEPTEMBER, 1, 0, 0,
652                                                (int)(0.5 * millisPerHour));
653 
654         if (tz.getRawOffset() != -5 * millisPerHour)
655             fail("Got back a raw offset of " + (tz.getRawOffset() / millisPerHour) +
656                   " hours instead of -5 hours.");
657         if (!tz.useDaylightTime())
658             fail("Test time zone should use DST but claims it doesn't.");
659         if (tz.getDSTSavings() != 0.5 * millisPerHour)
660             fail("Set DST offset to 0.5 hour, but got back " + (tz.getDSTSavings() /
661                                                                  millisPerHour) + " hours instead.");
662 
663         int offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JANUARY, 1,
664                                   Calendar.THURSDAY, 10 * millisPerHour);
665         if (offset != -5 * millisPerHour)
666             fail("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got "
667                   + (offset / millisPerHour) + " hours.");
668 
669         offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JUNE, 1, Calendar.MONDAY,
670                               10 * millisPerHour);
671         if (offset != -4.5 * millisPerHour)
672             fail("The offset for 10 AM, 6/1/98 should have been -4.5 hours, but we got "
673                   + (offset / millisPerHour) + " hours.");
674 
675         tz.setDSTSavings(millisPerHour);
676         offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JANUARY, 1,
677                               Calendar.THURSDAY, 10 * millisPerHour);
678         if (offset != -5 * millisPerHour)
679             fail("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got "
680                   + (offset / millisPerHour) + " hours.");
681 
682         offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JUNE, 1, Calendar.MONDAY,
683                               10 * millisPerHour);
684         if (offset != -4 * millisPerHour)
685             fail("The offset for 10 AM, 6/1/98 (with a 1-hour DST offset) should have been -4 hours, but we got "
686                   + (offset / millisPerHour) + " hours.");
687     }
688 
689     /**
690      * Bug 4107570
691      */
692     @Test
693     public void TestAlternateRules() {
694         // Like TestDSTSavings, this test should probably be integrated somehow with the main
695         // test at the top of this class, but I didn't have time to figure out how to do that.
696         //                      --rtg 1/28/98
697 
698         SimpleTimeZone tz = new SimpleTimeZone(-5 * millisPerHour, "alternateRuleTest");
699 
700         // test the day-of-month API
701         tz.setStartRule(Calendar.MARCH, 10, 12 * millisPerHour);
702         tz.setEndRule(Calendar.OCTOBER, 20, 12 * millisPerHour);
703 
704         int offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 5,
705                                   Calendar.THURSDAY, 10 * millisPerHour);
706         if (offset != -5 * millisPerHour)
707             fail("The offset for 10AM, 3/5/98 should have been -5 hours, but we got "
708                   + (offset / millisPerHour) + " hours.");
709 
710         offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 15,
711                               Calendar.SUNDAY, 10 * millisPerHour);
712         if (offset != -4 * millisPerHour)
713             fail("The offset for 10AM, 3/15/98 should have been -4 hours, but we got "
714                   + (offset / millisPerHour) + " hours.");
715 
716         offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 15,
717                               Calendar.THURSDAY, 10 * millisPerHour);
718         if (offset != -4 * millisPerHour)
719             fail("The offset for 10AM, 10/15/98 should have been -4 hours, but we got "
720                   + (offset / millisPerHour) + " hours.");
721 
722         offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 25,
723                               Calendar.SUNDAY, 10 * millisPerHour);
724         if (offset != -5 * millisPerHour)
725             fail("The offset for 10AM, 10/25/98 should have been -5 hours, but we got "
726                   + (offset / millisPerHour) + " hours.");
727 
728         // test the day-of-week-after-day-in-month API
729         tz.setStartRule(Calendar.MARCH, 10, Calendar.FRIDAY, 12 * millisPerHour, true);
730         tz.setEndRule(Calendar.OCTOBER, 20, Calendar.FRIDAY, 12 * millisPerHour, false);
731 
732         offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 11,
733                               Calendar.WEDNESDAY, 10 * millisPerHour);
734         if (offset != -5 * millisPerHour)
735             fail("The offset for 10AM, 3/11/98 should have been -5 hours, but we got "
736                   + (offset / millisPerHour) + " hours.");
737 
738         offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 14,
739                               Calendar.SATURDAY, 10 * millisPerHour);
740         if (offset != -4 * millisPerHour)
741             fail("The offset for 10AM, 3/14/98 should have been -4 hours, but we got "
742                   + (offset / millisPerHour) + " hours.");
743 
744         offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 15,
745                               Calendar.THURSDAY, 10 * millisPerHour);
746         if (offset != -4 * millisPerHour)
747             fail("The offset for 10AM, 10/15/98 should have been -4 hours, but we got "
748                   + (offset / millisPerHour) + " hours.");
749 
750         offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 17,
751                               Calendar.SATURDAY, 10 * millisPerHour);
752         if (offset != -5 * millisPerHour)
753             fail("The offset for 10AM, 10/17/98 should have been -5 hours, but we got "
754                   + (offset / millisPerHour) + " hours.");
755     }
756 }
757 
758 //eof
< prev index next >