< prev index next >

test/jdk/java/util/TimeZone/TimeZoneRegression.java

Print this page

   1 /*
   2  * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  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 4052967 4073209 4073215 4084933 4096952 4109314 4126678 4151406 4151429
  27  * 4154525 4154537 4154542 4154650 4159922 4162593 4173604 4176686 4184229 4208960
  28  * 4966229 6433179 6851214 8007520 8008577
  29  * @library /java/text/testlib
  30  * @run main/othervm -Djava.locale.providers=COMPAT,SPI TimeZoneRegression
  31  */
  32 
  33 import java.util.*;
  34 import java.io.*;
  35 import java.text.*;
  36 
  37 public class TimeZoneRegression extends IntlTest {
  38 
  39     public static void main(String[] args) throws Exception {
  40         new TimeZoneRegression().run(args);
  41     }
  42 

  43     public void Test4073209() {
  44         TimeZone z1 = TimeZone.getTimeZone("PST");
  45         TimeZone z2 = TimeZone.getTimeZone("PST");
  46         if (z1 == z2) {
  47             errln("Fail: TimeZone should return clones");
  48         }
  49     }
  50 
  51     @SuppressWarnings("deprecation")

  52     public void Test4073215() {
  53         SimpleTimeZone z = new SimpleTimeZone(0, "GMT");
  54         if (z.useDaylightTime()) {
  55             errln("Fail: Fix test to start with non-DST zone");
  56         }
  57         z.setStartRule(Calendar.FEBRUARY, 1, Calendar.SUNDAY, 0);
  58         z.setEndRule(Calendar.MARCH, -1, Calendar.SUNDAY, 0);
  59         if (!z.useDaylightTime()) {
  60             errln("Fail: DST not active");
  61         }
  62         if (z.inDaylightTime(new Date(97, Calendar.JANUARY, 31)) ||
  63             !z.inDaylightTime(new Date(97, Calendar.MARCH, 1)) ||
  64             z.inDaylightTime(new Date(97, Calendar.MARCH, 31))) {
  65             errln("Fail: DST not working as expected");
  66         }
  67     }
  68 
  69     /**
  70      * The expected behavior of TimeZone around the boundaries is:
  71      * (Assume transition time of 2:00 AM)
  72      *    day of onset 1:59 AM STD  = display name 1:59 AM ST
  73      *                 2:00 AM STD  = display name 3:00 AM DT
  74      *    day of end   0:59 AM STD  = display name 1:59 AM DT
  75      *                 1:00 AM STD  = display name 1:00 AM ST
  76      */

  77     public void Test4084933() {
  78         // test both SimpleTimeZone and ZoneInfo objects.
  79         // @since 1.4
  80         sub4084933(getPST());
  81         sub4084933(TimeZone.getTimeZone("PST"));
  82     }
  83 
  84     private void sub4084933(TimeZone tz) {
  85         long offset1 = tz.getOffset(1,
  86             1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (2*60*60*1000));
  87         long offset2 = tz.getOffset(1,
  88             1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (2*60*60*1000)-1);
  89 
  90         long offset3 = tz.getOffset(1,
  91             1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (1*60*60*1000));
  92         long offset4 = tz.getOffset(1,
  93             1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (1*60*60*1000)-1);
  94 
  95         /*
  96          *  The following was added just for consistency.  It shows that going *to* Daylight
  97          *  Savings Time (PDT) does work at 2am.
  98          */
  99 
 100         long offset5 = tz.getOffset(1,
 101             1997, Calendar.APRIL, 6, Calendar.SUNDAY, (2*60*60*1000));
 102         long offset6 = tz.getOffset(1,
 103             1997, Calendar.APRIL, 6, Calendar.SUNDAY, (2*60*60*1000)-1);
 104 
 105         long offset7 = tz.getOffset(1,
 106             1997, Calendar.APRIL, 6, Calendar.SUNDAY, (1*60*60*1000));
 107         long offset8 = tz.getOffset(1,
 108             1997, Calendar.APRIL, 6, Calendar.SUNDAY, (1*60*60*1000)-1);
 109 
 110         long SToffset = -8 * 60*60*1000L;
 111         long DToffset = -7 * 60*60*1000L;
 112         if (offset1 != SToffset || offset2 != SToffset ||
 113             offset3 != SToffset || offset4 != DToffset ||
 114             offset5 != DToffset || offset6 != SToffset ||
 115             offset7 != SToffset || offset8 != SToffset)
 116             errln("Fail: TimeZone misbehaving"); {
 117         }
 118     }
 119 

 120     public void Test4096952() {
 121         String[] ZONES = { "GMT", "MET", "IST" };
 122         boolean pass = true;
 123         try {
 124             for (int i=0; i<ZONES.length; ++i) {
 125                 TimeZone zone = TimeZone.getTimeZone(ZONES[i]);
 126                 if (!zone.getID().equals(ZONES[i]))
 127                     errln("Fail: Test broken; zones not instantiating");
 128 
 129                 ByteArrayOutputStream baos;
 130                 ObjectOutputStream ostream =
 131                     new ObjectOutputStream(baos = new
 132                                            ByteArrayOutputStream());
 133                 ostream.writeObject(zone);
 134                 ostream.close();
 135                 baos.close();
 136                 ObjectInputStream istream =
 137                     new ObjectInputStream(new
 138                                           ByteArrayInputStream(baos.toByteArray()));
 139                 TimeZone frankenZone = (TimeZone) istream.readObject();
 140                 //logln("Zone:        " + zone);
 141                 //logln("FrankenZone: " + frankenZone);
 142                 if (!zone.equals(frankenZone)) {
 143                     logln("TimeZone " + zone.getID() +
 144                           " not equal to serialized/deserialized one");
 145                     pass = false;
 146                 }
 147             }
 148             if (!pass) errln("Fail: TimeZone serialization/equality bug");
 149         }
 150         catch (IOException e) {
 151             errln("Fail: " + e);
 152             e.printStackTrace();
 153         }
 154         catch (ClassNotFoundException e) {
 155             errln("Fail: " + e);
 156             e.printStackTrace();
 157         }
 158     }
 159 

 160     public void Test4109314() {
 161         Locale locale = Locale.getDefault();
 162         if (!TestUtils.usesGregorianCalendar(locale)) {
 163             logln("Skipping this test because locale is " + locale);
 164             return;
 165         }
 166 
 167         // test both SimpleTimeZone and ZoneInfo objects.
 168         // @since 1.4
 169         sub4109314(getPST());
 170         sub4109314(TimeZone.getTimeZone("PST"));
 171     }
 172 
 173 
 174     @SuppressWarnings("deprecation")
 175     private void sub4109314(TimeZone PST) {
 176         GregorianCalendar testCal = (GregorianCalendar)Calendar.getInstance();
 177         Object[] testData = {
 178             PST, new Date(98,Calendar.APRIL,4,22,0), new Date(98, Calendar.APRIL, 5,6,0),
 179             PST, new Date(98,Calendar.OCTOBER,24,22,0), new Date(98,Calendar.OCTOBER,25,6,0),
 180         };
 181         boolean pass=true;
 182         for (int i=0; i<testData.length; i+=3) {
 183             testCal.setTimeZone((TimeZone) testData[i]);
 184             long t = ((Date)testData[i+1]).getTime();
 185             Date end = (Date) testData[i+2];
 186             while (t < end.getTime()) {
 187                 testCal.setTime(new Date(t));
 188                 if (!checkCalendar314(testCal, (TimeZone) testData[i]))
 189                     pass = false;
 190                 t += 60*60*1000L;
 191             }
 192         }
 193         if (!pass) errln("Fail: TZ API inconsistent");
 194     }
 195 
 196     boolean checkCalendar314(GregorianCalendar testCal, TimeZone testTZ) {
 197         // GregorianCalendar testCal = (GregorianCalendar)aCal.clone();
 198 
 199         final int ONE_DAY = 24*60*60*1000;
 200 
 201         int tzOffset, tzRawOffset;
 202         Float tzOffsetFloat,tzRawOffsetFloat;
 203         // Here is where the user made an error.  They were passing in the value of
 204         // the MILLSECOND field; you need to pass in the millis in the day in STANDARD
 205         // time.
 206         int millis = testCal.get(Calendar.MILLISECOND) +
 207             1000 * (testCal.get(Calendar.SECOND) +
 208                     60 * (testCal.get(Calendar.MINUTE) +
 209                           60 * (testCal.get(Calendar.HOUR_OF_DAY)))) -
 210             testCal.get(Calendar.DST_OFFSET);
 211 
 212         /* Fix up millis to be in range.  ASSUME THAT WE ARE NOT AT THE
 213          * BEGINNING OR END OF A MONTH.  We must add this code because

 251             inDaylightTimeString = " DST ";
 252             passed = (tzOffset == (tzRawOffset + 3600000));
 253         }
 254         else
 255         {
 256             inDaylightTimeString = "     ";
 257             passed = (tzOffset == tzRawOffset);
 258         }
 259 
 260         String output = testTZ.getID() + " " + sdf.format(testDate) +
 261             " Offset(" + tzOffsetFloat + ")" +
 262             " RawOffset(" + tzRawOffsetFloat + ")" +
 263             " " + millis/(float)3600000 + " " +
 264             inDaylightTimeString;
 265 
 266         if (passed)
 267             output += "     ";
 268         else
 269             output += "ERROR";
 270 
 271         if (passed) logln(output); else errln(output);
 272         return passed;
 273     }
 274 
 275     /**
 276      * CANNOT REPRODUDE
 277      *
 278      * Yet another _alleged_ bug in TimeZone.getOffset(), a method that never
 279      * should have been made public.  It's simply too hard to use correctly.
 280      *
 281      * The original test code failed to do the following:
 282      * (1) Call Calendar.setTime() before getting the fields!
 283      * (2) Use the right millis (as usual) for getOffset(); they were passing
 284      *     in the MILLIS field, instead of the STANDARD MILLIS IN DAY.
 285      * When you fix these two problems, the test passes, as expected.
 286      */

 287     public void Test4126678() {
 288         Locale locale = Locale.getDefault();
 289         if (!TestUtils.usesGregorianCalendar(locale)) {
 290             logln("Skipping this test because locale is " + locale);
 291             return;
 292         }
 293 
 294         // Note: this test depends on the PST time zone.
 295         TimeZone initialZone = TimeZone.getDefault();
 296 
 297         // test both SimpleTimeZone and ZoneInfo objects.
 298         // @since 1.4
 299         sub4126678(getPST());
 300         sub4126678(TimeZone.getTimeZone("PST"));
 301 
 302         // restore the initial time zone so that this test case
 303         // doesn't affect the others.
 304         TimeZone.setDefault(initialZone);
 305     }
 306 
 307     @SuppressWarnings("deprecation")
 308     private void sub4126678(TimeZone tz) {
 309         Calendar cal = Calendar.getInstance();
 310         TimeZone.setDefault(tz);
 311         cal.setTimeZone(tz);
 312 
 313         Date dt = new Date(1998-1900, Calendar.APRIL, 5, 10, 0);
 314         // the dt value is local time in PST.
 315         if (!tz.inDaylightTime(dt))
 316             errln("We're not in Daylight Savings Time and we should be.\n");
 317 
 318         cal.setTime(dt);
 319         int era = cal.get(Calendar.ERA);
 320         int year = cal.get(Calendar.YEAR);
 321         int month = cal.get(Calendar.MONTH);
 322         int day = cal.get(Calendar.DATE);
 323         int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
 324         int millis = cal.get(Calendar.MILLISECOND) +
 325             (cal.get(Calendar.SECOND) +
 326              (cal.get(Calendar.MINUTE) +
 327               (cal.get(Calendar.HOUR) * 60) * 60) * 1000) -
 328             cal.get(Calendar.DST_OFFSET);
 329 
 330         long offset = tz.getOffset(era, year, month, day, dayOfWeek, millis);
 331         long raw_offset = tz.getRawOffset();
 332         if (offset == raw_offset) {
 333             errln("Offsets should not match when in DST");
 334         }
 335     }
 336 
 337     /**
 338      * TimeZone.getAvailableIDs(int) throws exception for certain values,
 339      * due to a faulty constant in TimeZone.java.
 340      */

 341     public void Test4151406() {
 342         int max = 0;
 343         for (int h=-28; h<=30; ++h) {
 344             // h is in half-hours from GMT; rawoffset is in millis
 345             int rawoffset = h * 1800000;
 346             int hh = (h<0) ? -h : h;
 347             String hname = ((h<0) ? "GMT-" : "GMT+") +
 348                 ((hh/2 < 10) ? "0" : "") +
 349                 (hh/2) + ':' +
 350                 ((hh%2==0) ? "00" : "30");
 351             try {
 352                 String[] ids = TimeZone.getAvailableIDs(rawoffset);
 353                 if (ids.length > max) max = ids.length;
 354                 logln(hname + ' ' + ids.length +
 355                       ((ids.length > 0) ? (" e.g. " + ids[0]) : ""));
 356             } catch (Exception e) {
 357                 errln(hname + ' ' + "Fail: " + e);
 358             }
 359         }
 360         logln("Maximum zones per offset = " + max);
 361     }
 362 

 363     public void Test4151429() {
 364         try {
 365             TimeZone tz = TimeZone.getTimeZone("GMT");
 366             String name = tz.getDisplayName(true, Integer.MAX_VALUE,
 367                                             Locale.getDefault());
 368             errln("IllegalArgumentException not thrown by TimeZone.getDisplayName()");
 369         } catch(IllegalArgumentException e) {}
 370     }
 371 
 372     /**
 373      * SimpleTimeZone accepts illegal DST savings values.  These values
 374      * must be non-zero.  There is no upper limit at this time.
 375      */

 376     public void Test4154525() {
 377         final int GOOD = 1, BAD = 0;
 378         int[] DATA = {
 379             1, GOOD,
 380             0, BAD,
 381             -1, BAD,
 382             60*60*1000, GOOD,
 383             Integer.MIN_VALUE, BAD,
 384             // Integer.MAX_VALUE, ?, // no upper limit on DST savings at this time
 385         };
 386         for (int i=0; i<DATA.length; i+=2) {
 387             int savings = DATA[i];
 388             boolean valid = DATA[i+1] == GOOD;
 389             String method = null;
 390             for (int j=0; j<2; ++j) {
 391                 try {
 392                     switch (j) {
 393                     case 0:
 394                         method = "constructor";
 395                         SimpleTimeZone z = new SimpleTimeZone(0, "id",
 396                             Calendar.JANUARY, 1, 0, 0,
 397                             Calendar.MARCH, 1, 0, 0,
 398                             savings); // <- what we're interested in
 399                         break;
 400                     case 1:
 401                         method = "setDSTSavings()";
 402                         z = new SimpleTimeZone(0, "GMT");
 403                         z.setDSTSavings(savings);
 404                         break;
 405                     }
 406                     if (valid) {
 407                         logln("Pass: DST savings of " + savings + " accepted by " + method);
 408                     } else {
 409                         errln("Fail: DST savings of " + savings + " accepted by " + method);
 410                     }
 411                 } catch (IllegalArgumentException e) {
 412                     if (valid) {
 413                         errln("Fail: DST savings of " + savings + " to " + method + " gave " + e);
 414                     } else {
 415                         logln("Pass: DST savings of " + savings + " to " + method + " gave " + e);
 416                     }
 417                 }
 418             }
 419         }
 420     }
 421 
 422     /**
 423      * SimpleTimeZone.hasSameRules() doesn't work for zones with no DST
 424      * and different DST parameters.
 425      */

 426     public void Test4154537() {
 427         // tz1 and tz2 have no DST and different rule parameters
 428         SimpleTimeZone tz1 = new SimpleTimeZone(0, "1", 0, 0, 0, 0, 2, 0, 0, 0);
 429         SimpleTimeZone tz2 = new SimpleTimeZone(0, "2", 1, 0, 0, 0, 3, 0, 0, 0);
 430         // tza and tzA have the same rule params
 431         SimpleTimeZone tza = new SimpleTimeZone(0, "a", 0, 1, 0, 0, 3, 2, 0, 0);
 432         SimpleTimeZone tzA = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 3, 2, 0, 0);
 433         // tzb differs from tza
 434         SimpleTimeZone tzb = new SimpleTimeZone(0, "b", 0, 1, 0, 0, 3, 1, 0, 0);
 435         if (tz1.useDaylightTime() || tz2.useDaylightTime() ||
 436             !tza.useDaylightTime() || !tzA.useDaylightTime() ||
 437             !tzb.useDaylightTime()) {
 438             errln("Test is broken -- rewrite it");
 439         }
 440         if (!tza.hasSameRules(tzA) || tza.hasSameRules(tzb)) {
 441             errln("Fail: hasSameRules() broken for zones with rules");
 442         }
 443         if (!tz1.hasSameRules(tz2)) {
 444             errln("Fail: hasSameRules() returns false for zones without rules");
 445             errln("zone 1 = " + tz1);
 446             errln("zone 2 = " + tz2);
 447         }
 448     }
 449 
 450     /**
 451      * SimpleTimeZone constructors, setStartRule(), and setEndRule() don't
 452      * check for out-of-range arguments.
 453      */

 454     public void Test4154542() {
 455         final int GOOD = 1;
 456         final int BAD  = 0;
 457 
 458         final int GOOD_MONTH       = Calendar.JANUARY;
 459         final int GOOD_DAY         = 1;
 460         final int GOOD_DAY_OF_WEEK = Calendar.SUNDAY;
 461         final int GOOD_TIME        = 0;
 462 
 463         int[] DATA = {
 464             GOOD, Integer.MIN_VALUE,    0,  Integer.MAX_VALUE,   Integer.MIN_VALUE,
 465             GOOD, Calendar.JANUARY,    -5,  Calendar.SUNDAY,     0,
 466             GOOD, Calendar.DECEMBER,    5,  Calendar.SATURDAY,   24*60*60*1000-1,
 467             GOOD, Calendar.DECEMBER,    5,  Calendar.SATURDAY,   24*60*60*1000,
 468             BAD,  Calendar.DECEMBER,    5,  Calendar.SATURDAY,   24*60*60*1000+1,
 469             BAD,  Calendar.DECEMBER,    5,  Calendar.SATURDAY,  -1,
 470             BAD,  Calendar.JANUARY,    -6,  Calendar.SUNDAY,     0,
 471             BAD,  Calendar.DECEMBER,    6,  Calendar.SATURDAY,   24*60*60*1000,
 472             GOOD, Calendar.DECEMBER,    1,  0,                   0,
 473             GOOD, Calendar.DECEMBER,   31,  0,                   0,

 479             GOOD, Calendar.DECEMBER,   31, -Calendar.SATURDAY,   0,
 480             BAD,  Calendar.DECEMBER,   32, -Calendar.SATURDAY,   0,
 481             BAD,  Calendar.DECEMBER,  -32, -Calendar.SATURDAY,   0,
 482             BAD,  Calendar.DECEMBER,   31, -Calendar.SATURDAY-1, 0,
 483         };
 484         SimpleTimeZone zone = new SimpleTimeZone(0, "Z");
 485         for (int i=0; i<DATA.length; i+=5) {
 486             boolean shouldBeGood = (DATA[i] == GOOD);
 487             int month     = DATA[i+1];
 488             int day       = DATA[i+2];
 489             int dayOfWeek = DATA[i+3];
 490             int time      = DATA[i+4];
 491 
 492             Exception ex = null;
 493             try {
 494                 zone.setStartRule(month, day, dayOfWeek, time);
 495             } catch (IllegalArgumentException e) {
 496                 ex = e;
 497             }
 498             if ((ex == null) != shouldBeGood) {
 499                 errln("setStartRule(month=" + month + ", day=" + day +
 500                       ", dayOfWeek=" + dayOfWeek + ", time=" + time +
 501                       (shouldBeGood ? (") should work but throws " + ex)
 502                        : ") should fail but doesn't"));
 503             }
 504 
 505             ex = null;
 506             try {
 507                 zone.setEndRule(month, day, dayOfWeek, time);
 508             } catch (IllegalArgumentException e) {
 509                 ex = e;
 510             }
 511             if ((ex == null) != shouldBeGood) {
 512                 errln("setEndRule(month=" + month + ", day=" + day +
 513                       ", dayOfWeek=" + dayOfWeek + ", time=" + time +
 514                       (shouldBeGood ? (") should work but throws " + ex)
 515                        : ") should fail but doesn't"));
 516             }
 517 
 518             ex = null;
 519             try {
 520                 SimpleTimeZone temp = new SimpleTimeZone(0, "Z",
 521                         month, day, dayOfWeek, time,
 522                         GOOD_MONTH, GOOD_DAY, GOOD_DAY_OF_WEEK, GOOD_TIME);
 523             } catch (IllegalArgumentException e) {
 524                 ex = e;
 525             }
 526             if ((ex == null) != shouldBeGood) {
 527                 errln("SimpleTimeZone(month=" + month + ", day=" + day +
 528                       ", dayOfWeek=" + dayOfWeek + ", time=" + time +
 529                       (shouldBeGood ? (", <end>) should work but throws " + ex)
 530                        : ", <end>) should fail but doesn't"));
 531             }
 532 
 533             ex = null;
 534             try {
 535                 SimpleTimeZone temp = new SimpleTimeZone(0, "Z",
 536                         GOOD_MONTH, GOOD_DAY, GOOD_DAY_OF_WEEK, GOOD_TIME,
 537                         month, day, dayOfWeek, time);
 538             } catch (IllegalArgumentException e) {
 539                 ex = e;
 540             }
 541             if ((ex == null) != shouldBeGood) {
 542                 errln("SimpleTimeZone(<start>, month=" + month + ", day=" + day +
 543                       ", dayOfWeek=" + dayOfWeek + ", time=" + time +
 544                       (shouldBeGood ? (") should work but throws " + ex)
 545                        : ") should fail but doesn't"));
 546             }
 547         }
 548     }
 549 
 550     /**
 551      * SimpleTimeZone.getOffset accepts illegal arguments.
 552      */

 553     public void Test4154650() {
 554         final int GOOD=1, BAD=0;
 555         final int GOOD_ERA=GregorianCalendar.AD, GOOD_YEAR=1998, GOOD_MONTH=Calendar.AUGUST;
 556         final int GOOD_DAY=2, GOOD_DOW=Calendar.SUNDAY, GOOD_TIME=16*3600000;
 557         int[] DATA = {
 558             GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
 559 
 560             GOOD, GregorianCalendar.BC, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
 561             GOOD, GregorianCalendar.AD, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
 562             BAD,  GregorianCalendar.BC-1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
 563             BAD,  GregorianCalendar.AD+1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
 564 
 565             GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, GOOD_DAY, GOOD_DOW, GOOD_TIME,
 566             GOOD, GOOD_ERA, GOOD_YEAR, Calendar.DECEMBER, GOOD_DAY, GOOD_DOW, GOOD_TIME,
 567             BAD,  GOOD_ERA, GOOD_YEAR, Calendar.JANUARY-1, GOOD_DAY, GOOD_DOW, GOOD_TIME,
 568             BAD,  GOOD_ERA, GOOD_YEAR, Calendar.DECEMBER+1, GOOD_DAY, GOOD_DOW, GOOD_TIME,
 569 
 570             GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 1, GOOD_DOW, GOOD_TIME,
 571             GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 31, GOOD_DOW, GOOD_TIME,
 572             BAD,  GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 0, GOOD_DOW, GOOD_TIME,

 577             BAD,  GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SUNDAY-1, GOOD_TIME,
 578             BAD,  GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SATURDAY+1, GOOD_TIME,
 579 
 580             GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 0,
 581             GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000-1,
 582             BAD,  GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, -1,
 583             BAD,  GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000,
 584         };
 585 
 586         TimeZone tz = TimeZone.getDefault();
 587         for (int i=0; i<DATA.length; i+=7) {
 588             boolean good = DATA[i] == GOOD;
 589             IllegalArgumentException e = null;
 590             try {
 591                 int offset = tz.getOffset(DATA[i+1], DATA[i+2], DATA[i+3],
 592                                           DATA[i+4], DATA[i+5], DATA[i+6]);
 593            } catch (IllegalArgumentException ex) {
 594                 e = ex;
 595             }
 596             if (good != (e == null)) {
 597                 errln("Fail: getOffset(" +
 598                       DATA[i+1] + ", " + DATA[i+2] + ", " + DATA[i+3] + ", " +
 599                       DATA[i+4] + ", " + DATA[i+5] + ", " + DATA[i+6] +
 600                       (good ? (") threw " + e) : ") accepts invalid args"));
 601             }
 602         }
 603     }
 604 
 605     /**
 606      * TimeZone constructors allow null IDs.
 607      */

 608     public void Test4159922() {
 609         TimeZone z = null;
 610 
 611         // TimeZone API.  Only hasSameRules() and setDefault() should
 612         // allow null.
 613         try {
 614             z = TimeZone.getTimeZone((String)null);
 615             errln("FAIL: Null allowed in getTimeZone");
 616         } catch (NullPointerException e) {}
 617         z = TimeZone.getTimeZone("GMT");
 618         try {
 619             z.getDisplayName(false, TimeZone.SHORT, null);
 620             errln("FAIL: Null allowed in getDisplayName(3)");
 621         } catch (NullPointerException e) {}
 622         try {
 623             z.getDisplayName(null);
 624             errln("FAIL: Null allowed in getDisplayName(1)");
 625         } catch (NullPointerException e) {}
 626         try {
 627             if (z.hasSameRules(null)) {
 628                 errln("FAIL: hasSameRules returned true");
 629             }
 630         } catch (NullPointerException e) {
 631             errln("FAIL: Null NOT allowed in hasSameRules");
 632         }
 633         try {
 634             z.inDaylightTime(null);
 635             errln("FAIL: Null allowed in inDaylightTime");
 636         } catch (NullPointerException e) {}
 637         try {
 638             z.setID(null);
 639             errln("FAIL: Null allowed in setID");
 640         } catch (NullPointerException e) {}
 641 
 642         TimeZone save = TimeZone.getDefault();
 643         try {
 644             TimeZone.setDefault(null);
 645         } catch (NullPointerException e) {
 646             errln("FAIL: Null NOT allowed in setDefault");
 647         } finally {
 648             TimeZone.setDefault(save);
 649         }
 650 
 651         // SimpleTimeZone API
 652         SimpleTimeZone s = null;
 653         try {
 654             s = new SimpleTimeZone(0, null);
 655             errln("FAIL: Null allowed in SimpleTimeZone(2)");
 656         } catch (NullPointerException e) {}
 657         try {
 658             s = new SimpleTimeZone(0, null, 0, 1, 0, 0, 0, 1, 0, 0);
 659             errln("FAIL: Null allowed in SimpleTimeZone(10)");
 660         } catch (NullPointerException e) {}
 661         try {
 662             s = new SimpleTimeZone(0, null, 0, 1, 0, 0, 0, 1, 0, 0, 1000);
 663             errln("FAIL: Null allowed in SimpleTimeZone(11)");
 664         } catch (NullPointerException e) {}
 665     }
 666 
 667     /**
 668      * TimeZone broken at midnight.  The TimeZone code fails to handle
 669      * transitions at midnight correctly.
 670      */
 671     @SuppressWarnings("deprecation")

 672     public void Test4162593() {
 673         SimpleDateFormat fmt = new SimpleDateFormat("z", Locale.US);
 674         final int ONE_HOUR = 60*60*1000;
 675         TimeZone initialZone = TimeZone.getDefault();
 676 
 677         SimpleTimeZone asuncion = new SimpleTimeZone(-4*ONE_HOUR, "America/Asuncion" /*PY%sT*/,
 678             Calendar.OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR,
 679             Calendar.MARCH, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR);
 680 
 681         /* Zone
 682          * Starting time
 683          * Transition expected between start+1H and start+2H
 684          */
 685         Object[] DATA = {
 686             new SimpleTimeZone(2*ONE_HOUR, "Asia/Damascus" /*EE%sT*/,
 687                 Calendar.APRIL, 1, 0 /*DOM*/, 0*ONE_HOUR,
 688                 Calendar.OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR),
 689             new int[] {98, Calendar.SEPTEMBER, 30, 22, 0},
 690             Boolean.TRUE,
 691 

 694             Boolean.FALSE,
 695 
 696             asuncion,
 697             new int[] {100, Calendar.FEBRUARY, 29, 22, 0},
 698             Boolean.TRUE,
 699         };
 700 
 701         String[] zone = new String[4];
 702 
 703         try {
 704             for (int j=0; j<DATA.length; j+=3) {
 705                 TimeZone tz = (TimeZone)DATA[j];
 706                 TimeZone.setDefault(tz);
 707                 fmt.setTimeZone(tz);
 708 
 709                 // Must construct the Date object AFTER setting the default zone
 710                 int[] p = (int[])DATA[j+1];
 711                 Date d = new Date(p[0], p[1], p[2], p[3], p[4]);
 712                 boolean transitionExpected = ((Boolean)DATA[j+2]).booleanValue();
 713 
 714                 logln(tz.getID() + ":");
 715                 for (int i=0; i<4; ++i) {
 716                     zone[i] = fmt.format(d);
 717                     logln("" + i + ": " + d);
 718                     d = new Date(d.getTime() + ONE_HOUR);
 719                 }
 720                 if (zone[0].equals(zone[1]) &&
 721                     (zone[1].equals(zone[2]) != transitionExpected) &&
 722                     zone[2].equals(zone[3])) {
 723                     logln("Ok: transition " + transitionExpected);
 724                 } else {
 725                     errln("Fail: boundary transition incorrect");
 726                 }
 727             }
 728         }
 729         finally {
 730             // restore the initial time zone so that this test case
 731             // doesn't affect the others.
 732             TimeZone.setDefault(initialZone);
 733         }
 734     }
 735 
 736     /**
 737      * TimeZone broken in last hour of year
 738      */

 739     public void Test4173604() {
 740         // test both SimpleTimeZone and ZoneInfo objects.
 741         // @since 1.4
 742         sub4173604(getPST());
 743         sub4173604(TimeZone.getTimeZone("PST"));
 744     }
 745 
 746     private void sub4173604(TimeZone pst) {
 747         int o22 = pst.getOffset(1, 1998, 11, 31, Calendar.THURSDAY, 22*60*60*1000);
 748         int o23 = pst.getOffset(1, 1998, 11, 31, Calendar.THURSDAY, 23*60*60*1000);
 749         int o00 = pst.getOffset(1, 1999, 0, 1, Calendar.FRIDAY, 0);
 750         if (o22 != o23 || o22 != o00) {
 751             errln("Offsets should be the same (for PST), but got: " +
 752                   "12/31 22:00 " + o22 +
 753                   ", 12/31 23:00 " + o23 +
 754                   ", 01/01 00:00 " + o00);
 755         }
 756 
 757         GregorianCalendar cal = new GregorianCalendar();
 758         cal.setTimeZone(pst);
 759         cal.clear();
 760         cal.set(1998, Calendar.JANUARY, 1);
 761         int lastDST = cal.get(Calendar.DST_OFFSET);
 762         int transitions = 0;
 763         int delta = 5;
 764         while (cal.get(Calendar.YEAR) < 2000) {
 765             cal.add(Calendar.MINUTE, delta);
 766             if (cal.get(Calendar.DST_OFFSET) != lastDST) {
 767                 ++transitions;
 768                 Calendar t = (Calendar)cal.clone();
 769                 t.add(Calendar.MINUTE, -delta);
 770                 logln(t.getTime() + "  " + t.get(Calendar.DST_OFFSET));
 771                 logln(cal.getTime() + "  " + (lastDST=cal.get(Calendar.DST_OFFSET)));
 772             }
 773         }
 774         if (transitions != 4) {
 775             errln("Saw " + transitions + " transitions; should have seen 4");
 776         }
 777     }
 778 
 779     /**
 780      * getDisplayName doesn't work with unusual savings/offsets.
 781      */
 782     @SuppressWarnings("deprecation")

 783     public void Test4176686() {
 784         // Construct a zone that does not observe DST but
 785         // that does have a DST savings (which should be ignored).
 786         int offset = 90 * 60000; // 1:30
 787         SimpleTimeZone z1 = new SimpleTimeZone(offset, "_std_zone_");
 788         z1.setDSTSavings(45 * 60000); // 0:45
 789 
 790         // Construct a zone that observes DST for the first 6 months.
 791         SimpleTimeZone z2 = new SimpleTimeZone(offset, "_dst_zone_");
 792         z2.setDSTSavings(45 * 60000); // 0:45
 793         z2.setStartRule(Calendar.JANUARY, 1, 0);
 794         z2.setEndRule(Calendar.JULY, 1, 0);
 795 
 796         // Also check DateFormat
 797         DateFormat fmt1 = new SimpleDateFormat("z");
 798         fmt1.setTimeZone(z1); // Format uses standard zone
 799         DateFormat fmt2 = new SimpleDateFormat("z");
 800         fmt2.setTimeZone(z2); // Format uses DST zone
 801         Date dst = new Date(1970-1900, Calendar.FEBRUARY, 1); // Time in DST
 802         Date std = new Date(1970-1900, Calendar.AUGUST, 1); // Time in standard

 810             "getDisplayName(true, SHORT)/std zone",
 811             z1.getDisplayName(true, TimeZone.SHORT), "GMT+01:30",
 812             "getDisplayName(true, LONG)/std zone",
 813             z1.getDisplayName(true, TimeZone.LONG ), "GMT+01:30",
 814             "getDisplayName(false, SHORT)/dst zone",
 815             z2.getDisplayName(false, TimeZone.SHORT), "GMT+01:30",
 816             "getDisplayName(false, LONG)/dst zone",
 817             z2.getDisplayName(false, TimeZone.LONG ), "GMT+01:30",
 818             "getDisplayName(true, SHORT)/dst zone",
 819             z2.getDisplayName(true, TimeZone.SHORT), "GMT+02:15",
 820             "getDisplayName(true, LONG)/dst zone",
 821             z2.getDisplayName(true, TimeZone.LONG ), "GMT+02:15",
 822             "DateFormat.format(std)/std zone", fmt1.format(std), "GMT+01:30",
 823             "DateFormat.format(dst)/std zone", fmt1.format(dst), "GMT+01:30",
 824             "DateFormat.format(std)/dst zone", fmt2.format(std), "GMT+01:30",
 825             "DateFormat.format(dst)/dst zone", fmt2.format(dst), "GMT+02:15",
 826         };
 827 
 828         for (int i=0; i<DATA.length; i+=3) {
 829             if (!DATA[i+1].equals(DATA[i+2])) {
 830                 errln("FAIL: " + DATA[i] + " -> " + DATA[i+1] + ", exp " + DATA[i+2]);
 831             }
 832         }
 833     }
 834 
 835     /**
 836      * SimpleTimeZone allows invalid DOM values.
 837      */

 838     public void Test4184229() {
 839         SimpleTimeZone zone = null;
 840         try {
 841             zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0);
 842             errln("Failed. No exception has been thrown for DOM -1 startDay");
 843         } catch(IllegalArgumentException e) {
 844             logln("(a) " + e.getMessage());
 845         }
 846         try {
 847             zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0);
 848             errln("Failed. No exception has been thrown for DOM -1 endDay");
 849         } catch(IllegalArgumentException e) {
 850             logln("(b) " + e.getMessage());
 851         }
 852         try {
 853             zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0, 1000);
 854             errln("Failed. No exception has been thrown for DOM -1 startDay +savings");
 855         } catch(IllegalArgumentException e) {
 856             logln("(c) " + e.getMessage());
 857         }
 858         try {
 859             zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0, 1000);
 860             errln("Failed. No exception has been thrown for DOM -1 endDay +savings");
 861         } catch(IllegalArgumentException e) {
 862             logln("(d) " + e.getMessage());
 863         }
 864         // Make a valid constructor call for subsequent tests.
 865         zone = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 0, 1, 0, 0);
 866         try {
 867             zone.setStartRule(0, -1, 0, 0);
 868             errln("Failed. No exception has been thrown for DOM -1 setStartRule +savings");
 869         } catch(IllegalArgumentException e) {
 870             logln("(e) " + e.getMessage());
 871         }
 872         try {
 873             zone.setStartRule(0, -1, 0);
 874             errln("Failed. No exception has been thrown for DOM -1 setStartRule");
 875         } catch(IllegalArgumentException e) {
 876             logln("(f) " + e.getMessage());
 877         }
 878         try {
 879             zone.setEndRule(0, -1, 0, 0);
 880             errln("Failed. No exception has been thrown for DOM -1 setEndRule +savings");
 881         } catch(IllegalArgumentException e) {
 882             logln("(g) " + e.getMessage());
 883         }
 884         try {
 885             zone.setEndRule(0, -1, 0);
 886             errln("Failed. No exception has been thrown for DOM -1 setEndRule");
 887         } catch(IllegalArgumentException e) {
 888             logln("(h) " + e.getMessage());
 889         }
 890     }
 891 
 892     /**
 893      * SimpleTimeZone.getOffset() throws IllegalArgumentException when to get
 894      * of 2/29/1996 (leap day).
 895      */

 896     public void Test4208960 () {
 897         // test both SimpleTimeZone and ZoneInfo objects.
 898         // @since 1.4
 899         sub4208960(getPST());
 900         sub4208960(TimeZone.getTimeZone("PST"));
 901     }
 902 
 903     private void sub4208960(TimeZone tz) {
 904         try {
 905             int offset = tz.getOffset(GregorianCalendar.AD, 1996, Calendar.FEBRUARY, 29,
 906                                       Calendar.THURSDAY, 0);
 907         } catch (IllegalArgumentException e) {
 908             errln("FAILED: to get TimeZone.getOffset(2/29/96)");
 909         }
 910         try {
 911             int offset = tz.getOffset(GregorianCalendar.AD, 1997, Calendar.FEBRUARY, 29,
 912                                       Calendar.THURSDAY, 0);
 913             errln("FAILED: TimeZone.getOffset(2/29/97) expected to throw Exception.");
 914         } catch (IllegalArgumentException e) {
 915             logln("got IllegalArgumentException");
 916         }
 917     }
 918 
 919     /**
 920      * 4966229: java.util.Date methods may works incorrect.
 921      * sun.util.calendar.ZoneInfo doesn't clone properly.
 922      */
 923     @SuppressWarnings("deprecation")

 924     public void Test4966229() {
 925         TimeZone savedTZ = TimeZone.getDefault();
 926         try {
 927             TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
 928             Date d = new Date(2100-1900, 5, 1); // specify year >2037
 929             TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
 930 
 931             Calendar cal = new GregorianCalendar(tz);
 932             cal.setTime(d);
 933 
 934             // Change the raw offset in tz
 935             int offset = tz.getRawOffset();
 936             tz.setRawOffset(0);
 937 
 938             TimeZone tz2 = (TimeZone) tz.clone();
 939             Calendar cal2 = new GregorianCalendar(tz2);
 940             cal2.setTime(d);
 941             int expectedHourOfDay = cal2.get(cal.HOUR_OF_DAY);
 942 
 943             // Restore the GMT offset in tz which shouldn't affect tz2
 944             tz.setRawOffset(offset);
 945             cal2.setTime(d);
 946             int hourOfDay = cal2.get(cal.HOUR_OF_DAY);
 947             if (hourOfDay != expectedHourOfDay) {
 948                 errln("wrong hour of day: got: " + hourOfDay
 949                       + ", expected: " + expectedHourOfDay);
 950             }
 951         } finally {
 952             TimeZone.setDefault(savedTZ);
 953         }
 954     }
 955 
 956     /**
 957      * 6433179: (tz) Incorrect DST end for America/Winnipeg and Canada/Central in 2038+
 958      */

 959     public void Test6433179() {
 960         // Use the old America/Winnipeg rule for testing. Note that
 961         // startMode is WALL_TIME for testing. It's actually
 962         // STANDARD_TIME, though.
 963         //Rule  Winn    1966    2005    -       Oct     lastSun 2:00s   0       S
 964         //Rule  Winn    1987    2005    -       Apr     Sun>=1  2:00s   1:00    D
 965         TimeZone tz = new SimpleTimeZone(-6*ONE_HOUR, "America/Winnipeg",
 966           Calendar.APRIL, 1, -Calendar.SUNDAY, 2*ONE_HOUR, SimpleTimeZone.WALL_TIME,
 967           Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME,
 968           1*ONE_HOUR);
 969         Calendar cal = Calendar.getInstance(tz, Locale.US);
 970         cal.clear();
 971         cal.set(2039, Calendar.OCTOBER, 1);
 972         cal.getTime();
 973         cal.set(cal.DAY_OF_WEEK, cal.SUNDAY);
 974         cal.set(cal.DAY_OF_WEEK_IN_MONTH, -1);
 975         cal.add(Calendar.HOUR_OF_DAY, 2);
 976         if (cal.get(cal.DST_OFFSET) == 0) {
 977             errln("Should still be in DST.");
 978         }
 979     }
 980 
 981     private static final int ONE_HOUR = 60 * 60 * 1000;
 982     /**
 983      * Returns an instance of SimpleTimeZone for
 984      * "PST". (TimeZone.getTimeZone() no longer returns a
 985      * SimpleTimeZone object.)
 986      * @since 1.4
 987      */
 988     private SimpleTimeZone getPST() {
 989         return new SimpleTimeZone(-8*ONE_HOUR, "PST",
 990                                   Calendar.APRIL, 1, -Calendar.SUNDAY, 2*ONE_HOUR,
 991                                   Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*ONE_HOUR,
 992                                   1*ONE_HOUR);
 993     }
 994 }
 995 //eof

   1 /*
   2  * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  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 4052967 4073209 4073215 4084933 4096952 4109314 4126678 4151406 4151429
  27  * 4154525 4154537 4154542 4154650 4159922 4162593 4173604 4176686 4184229 4208960
  28  * 4966229 6433179 6851214 8007520 8008577
  29  * @library /java/text/testlib
  30  * @run junit/othervm -Djava.locale.providers=COMPAT,SPI TimeZoneRegression
  31  */
  32 
  33 import java.util.*;
  34 import java.io.*;
  35 import java.text.*;
  36 
  37 import org.junit.jupiter.api.Test;
  38 
  39 import static org.junit.jupiter.api.Assertions.fail;
  40 
  41 public class TimeZoneRegression {
  42 
  43     @Test
  44     public void Test4073209() {
  45         TimeZone z1 = TimeZone.getTimeZone("PST");
  46         TimeZone z2 = TimeZone.getTimeZone("PST");
  47         if (z1 == z2) {
  48             fail("Fail: TimeZone should return clones");
  49         }
  50     }
  51 
  52     @SuppressWarnings("deprecation")
  53     @Test
  54     public void Test4073215() {
  55         SimpleTimeZone z = new SimpleTimeZone(0, "GMT");
  56         if (z.useDaylightTime()) {
  57             fail("Fail: Fix test to start with non-DST zone");
  58         }
  59         z.setStartRule(Calendar.FEBRUARY, 1, Calendar.SUNDAY, 0);
  60         z.setEndRule(Calendar.MARCH, -1, Calendar.SUNDAY, 0);
  61         if (!z.useDaylightTime()) {
  62             fail("Fail: DST not active");
  63         }
  64         if (z.inDaylightTime(new Date(97, Calendar.JANUARY, 31)) ||
  65             !z.inDaylightTime(new Date(97, Calendar.MARCH, 1)) ||
  66             z.inDaylightTime(new Date(97, Calendar.MARCH, 31))) {
  67             fail("Fail: DST not working as expected");
  68         }
  69     }
  70 
  71     /**
  72      * The expected behavior of TimeZone around the boundaries is:
  73      * (Assume transition time of 2:00 AM)
  74      *    day of onset 1:59 AM STD  = display name 1:59 AM ST
  75      *                 2:00 AM STD  = display name 3:00 AM DT
  76      *    day of end   0:59 AM STD  = display name 1:59 AM DT
  77      *                 1:00 AM STD  = display name 1:00 AM ST
  78      */
  79     @Test
  80     public void Test4084933() {
  81         // test both SimpleTimeZone and ZoneInfo objects.
  82         // @since 1.4
  83         sub4084933(getPST());
  84         sub4084933(TimeZone.getTimeZone("PST"));
  85     }
  86 
  87     private void sub4084933(TimeZone tz) {
  88         long offset1 = tz.getOffset(1,
  89             1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (2*60*60*1000));
  90         long offset2 = tz.getOffset(1,
  91             1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (2*60*60*1000)-1);
  92 
  93         long offset3 = tz.getOffset(1,
  94             1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (1*60*60*1000));
  95         long offset4 = tz.getOffset(1,
  96             1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (1*60*60*1000)-1);
  97 
  98         /*
  99          *  The following was added just for consistency.  It shows that going *to* Daylight
 100          *  Savings Time (PDT) does work at 2am.
 101          */
 102 
 103         long offset5 = tz.getOffset(1,
 104             1997, Calendar.APRIL, 6, Calendar.SUNDAY, (2*60*60*1000));
 105         long offset6 = tz.getOffset(1,
 106             1997, Calendar.APRIL, 6, Calendar.SUNDAY, (2*60*60*1000)-1);
 107 
 108         long offset7 = tz.getOffset(1,
 109             1997, Calendar.APRIL, 6, Calendar.SUNDAY, (1*60*60*1000));
 110         long offset8 = tz.getOffset(1,
 111             1997, Calendar.APRIL, 6, Calendar.SUNDAY, (1*60*60*1000)-1);
 112 
 113         long SToffset = -8 * 60*60*1000L;
 114         long DToffset = -7 * 60*60*1000L;
 115         if (offset1 != SToffset || offset2 != SToffset ||
 116             offset3 != SToffset || offset4 != DToffset ||
 117             offset5 != DToffset || offset6 != SToffset ||
 118             offset7 != SToffset || offset8 != SToffset)
 119             fail("Fail: TimeZone misbehaving"); {
 120         }
 121     }
 122 
 123     @Test
 124     public void Test4096952() {
 125         String[] ZONES = { "GMT", "MET", "IST" };
 126         boolean pass = true;
 127         try {
 128             for (int i=0; i<ZONES.length; ++i) {
 129                 TimeZone zone = TimeZone.getTimeZone(ZONES[i]);
 130                 if (!zone.getID().equals(ZONES[i]))
 131                     fail("Fail: Test broken; zones not instantiating");
 132 
 133                 ByteArrayOutputStream baos;
 134                 ObjectOutputStream ostream =
 135                     new ObjectOutputStream(baos = new
 136                                            ByteArrayOutputStream());
 137                 ostream.writeObject(zone);
 138                 ostream.close();
 139                 baos.close();
 140                 ObjectInputStream istream =
 141                     new ObjectInputStream(new
 142                                           ByteArrayInputStream(baos.toByteArray()));
 143                 TimeZone frankenZone = (TimeZone) istream.readObject();
 144                 //logln("Zone:        " + zone);
 145                 //logln("FrankenZone: " + frankenZone);
 146                 if (!zone.equals(frankenZone)) {
 147                     System.out.println("TimeZone " + zone.getID() +
 148                           " not equal to serialized/deserialized one");
 149                     pass = false;
 150                 }
 151             }
 152             if (!pass) fail("Fail: TimeZone serialization/equality bug");
 153         }
 154         catch (IOException e) {
 155             fail("Fail: " + e);
 156             e.printStackTrace();
 157         }
 158         catch (ClassNotFoundException e) {
 159             fail("Fail: " + e);
 160             e.printStackTrace();
 161         }
 162     }
 163 
 164     @Test
 165     public void Test4109314() {
 166         Locale locale = Locale.getDefault();
 167         if (!TestUtils.usesGregorianCalendar(locale)) {
 168             System.out.println("Skipping this test because locale is " + locale);
 169             return;
 170         }
 171 
 172         // test both SimpleTimeZone and ZoneInfo objects.
 173         // @since 1.4
 174         sub4109314(getPST());
 175         sub4109314(TimeZone.getTimeZone("PST"));
 176     }
 177 
 178 
 179     @SuppressWarnings("deprecation")
 180     private void sub4109314(TimeZone PST) {
 181         GregorianCalendar testCal = (GregorianCalendar)Calendar.getInstance();
 182         Object[] testData = {
 183             PST, new Date(98,Calendar.APRIL,4,22,0), new Date(98, Calendar.APRIL, 5,6,0),
 184             PST, new Date(98,Calendar.OCTOBER,24,22,0), new Date(98,Calendar.OCTOBER,25,6,0),
 185         };
 186         boolean pass=true;
 187         for (int i=0; i<testData.length; i+=3) {
 188             testCal.setTimeZone((TimeZone) testData[i]);
 189             long t = ((Date)testData[i+1]).getTime();
 190             Date end = (Date) testData[i+2];
 191             while (t < end.getTime()) {
 192                 testCal.setTime(new Date(t));
 193                 if (!checkCalendar314(testCal, (TimeZone) testData[i]))
 194                     pass = false;
 195                 t += 60*60*1000L;
 196             }
 197         }
 198         if (!pass) fail("Fail: TZ API inconsistent");
 199     }
 200 
 201     boolean checkCalendar314(GregorianCalendar testCal, TimeZone testTZ) {
 202         // GregorianCalendar testCal = (GregorianCalendar)aCal.clone();
 203 
 204         final int ONE_DAY = 24*60*60*1000;
 205 
 206         int tzOffset, tzRawOffset;
 207         Float tzOffsetFloat,tzRawOffsetFloat;
 208         // Here is where the user made an error.  They were passing in the value of
 209         // the MILLSECOND field; you need to pass in the millis in the day in STANDARD
 210         // time.
 211         int millis = testCal.get(Calendar.MILLISECOND) +
 212             1000 * (testCal.get(Calendar.SECOND) +
 213                     60 * (testCal.get(Calendar.MINUTE) +
 214                           60 * (testCal.get(Calendar.HOUR_OF_DAY)))) -
 215             testCal.get(Calendar.DST_OFFSET);
 216 
 217         /* Fix up millis to be in range.  ASSUME THAT WE ARE NOT AT THE
 218          * BEGINNING OR END OF A MONTH.  We must add this code because

 256             inDaylightTimeString = " DST ";
 257             passed = (tzOffset == (tzRawOffset + 3600000));
 258         }
 259         else
 260         {
 261             inDaylightTimeString = "     ";
 262             passed = (tzOffset == tzRawOffset);
 263         }
 264 
 265         String output = testTZ.getID() + " " + sdf.format(testDate) +
 266             " Offset(" + tzOffsetFloat + ")" +
 267             " RawOffset(" + tzRawOffsetFloat + ")" +
 268             " " + millis/(float)3600000 + " " +
 269             inDaylightTimeString;
 270 
 271         if (passed)
 272             output += "     ";
 273         else
 274             output += "ERROR";
 275 
 276         if (passed) System.out.println(output); else fail(output);
 277         return passed;
 278     }
 279 
 280     /**
 281      * CANNOT REPRODUDE
 282      *
 283      * Yet another _alleged_ bug in TimeZone.getOffset(), a method that never
 284      * should have been made public.  It's simply too hard to use correctly.
 285      *
 286      * The original test code failed to do the following:
 287      * (1) Call Calendar.setTime() before getting the fields!
 288      * (2) Use the right millis (as usual) for getOffset(); they were passing
 289      *     in the MILLIS field, instead of the STANDARD MILLIS IN DAY.
 290      * When you fix these two problems, the test passes, as expected.
 291      */
 292     @Test
 293     public void Test4126678() {
 294         Locale locale = Locale.getDefault();
 295         if (!TestUtils.usesGregorianCalendar(locale)) {
 296             System.out.println("Skipping this test because locale is " + locale);
 297             return;
 298         }
 299 
 300         // Note: this test depends on the PST time zone.
 301         TimeZone initialZone = TimeZone.getDefault();
 302 
 303         // test both SimpleTimeZone and ZoneInfo objects.
 304         // @since 1.4
 305         sub4126678(getPST());
 306         sub4126678(TimeZone.getTimeZone("PST"));
 307 
 308         // restore the initial time zone so that this test case
 309         // doesn't affect the others.
 310         TimeZone.setDefault(initialZone);
 311     }
 312 
 313     @SuppressWarnings("deprecation")
 314     private void sub4126678(TimeZone tz) {
 315         Calendar cal = Calendar.getInstance();
 316         TimeZone.setDefault(tz);
 317         cal.setTimeZone(tz);
 318 
 319         Date dt = new Date(1998-1900, Calendar.APRIL, 5, 10, 0);
 320         // the dt value is local time in PST.
 321         if (!tz.inDaylightTime(dt))
 322             fail("We're not in Daylight Savings Time and we should be.\n");
 323 
 324         cal.setTime(dt);
 325         int era = cal.get(Calendar.ERA);
 326         int year = cal.get(Calendar.YEAR);
 327         int month = cal.get(Calendar.MONTH);
 328         int day = cal.get(Calendar.DATE);
 329         int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
 330         int millis = cal.get(Calendar.MILLISECOND) +
 331             (cal.get(Calendar.SECOND) +
 332              (cal.get(Calendar.MINUTE) +
 333               (cal.get(Calendar.HOUR) * 60) * 60) * 1000) -
 334             cal.get(Calendar.DST_OFFSET);
 335 
 336         long offset = tz.getOffset(era, year, month, day, dayOfWeek, millis);
 337         long raw_offset = tz.getRawOffset();
 338         if (offset == raw_offset) {
 339             fail("Offsets should not match when in DST");
 340         }
 341     }
 342 
 343     /**
 344      * TimeZone.getAvailableIDs(int) throws exception for certain values,
 345      * due to a faulty constant in TimeZone.java.
 346      */
 347     @Test
 348     public void Test4151406() {
 349         int max = 0;
 350         for (int h=-28; h<=30; ++h) {
 351             // h is in half-hours from GMT; rawoffset is in millis
 352             int rawoffset = h * 1800000;
 353             int hh = (h<0) ? -h : h;
 354             String hname = ((h<0) ? "GMT-" : "GMT+") +
 355                 ((hh/2 < 10) ? "0" : "") +
 356                 (hh/2) + ':' +
 357                 ((hh%2==0) ? "00" : "30");
 358             try {
 359                 String[] ids = TimeZone.getAvailableIDs(rawoffset);
 360                 if (ids.length > max) max = ids.length;
 361                 System.out.println(hname + ' ' + ids.length +
 362                       ((ids.length > 0) ? (" e.g. " + ids[0]) : ""));
 363             } catch (Exception e) {
 364                 fail(hname + ' ' + "Fail: " + e);
 365             }
 366         }
 367         System.out.println("Maximum zones per offset = " + max);
 368     }
 369 
 370     @Test
 371     public void Test4151429() {
 372         try {
 373             TimeZone tz = TimeZone.getTimeZone("GMT");
 374             String name = tz.getDisplayName(true, Integer.MAX_VALUE,
 375                                             Locale.getDefault());
 376             fail("IllegalArgumentException not thrown by TimeZone.getDisplayName()");
 377         } catch(IllegalArgumentException e) {}
 378     }
 379 
 380     /**
 381      * SimpleTimeZone accepts illegal DST savings values.  These values
 382      * must be non-zero.  There is no upper limit at this time.
 383      */
 384     @Test
 385     public void Test4154525() {
 386         final int GOOD = 1, BAD = 0;
 387         int[] DATA = {
 388             1, GOOD,
 389             0, BAD,
 390             -1, BAD,
 391             60*60*1000, GOOD,
 392             Integer.MIN_VALUE, BAD,
 393             // Integer.MAX_VALUE, ?, // no upper limit on DST savings at this time
 394         };
 395         for (int i=0; i<DATA.length; i+=2) {
 396             int savings = DATA[i];
 397             boolean valid = DATA[i+1] == GOOD;
 398             String method = null;
 399             for (int j=0; j<2; ++j) {
 400                 try {
 401                     switch (j) {
 402                     case 0:
 403                         method = "constructor";
 404                         SimpleTimeZone z = new SimpleTimeZone(0, "id",
 405                             Calendar.JANUARY, 1, 0, 0,
 406                             Calendar.MARCH, 1, 0, 0,
 407                             savings); // <- what we're interested in
 408                         break;
 409                     case 1:
 410                         method = "setDSTSavings()";
 411                         z = new SimpleTimeZone(0, "GMT");
 412                         z.setDSTSavings(savings);
 413                         break;
 414                     }
 415                     if (valid) {
 416                         System.out.println("Pass: DST savings of " + savings + " accepted by " + method);
 417                     } else {
 418                         fail("Fail: DST savings of " + savings + " accepted by " + method);
 419                     }
 420                 } catch (IllegalArgumentException e) {
 421                     if (valid) {
 422                         fail("Fail: DST savings of " + savings + " to " + method + " gave " + e);
 423                     } else {
 424                         System.out.println("Pass: DST savings of " + savings + " to " + method + " gave " + e);
 425                     }
 426                 }
 427             }
 428         }
 429     }
 430 
 431     /**
 432      * SimpleTimeZone.hasSameRules() doesn't work for zones with no DST
 433      * and different DST parameters.
 434      */
 435     @Test
 436     public void Test4154537() {
 437         // tz1 and tz2 have no DST and different rule parameters
 438         SimpleTimeZone tz1 = new SimpleTimeZone(0, "1", 0, 0, 0, 0, 2, 0, 0, 0);
 439         SimpleTimeZone tz2 = new SimpleTimeZone(0, "2", 1, 0, 0, 0, 3, 0, 0, 0);
 440         // tza and tzA have the same rule params
 441         SimpleTimeZone tza = new SimpleTimeZone(0, "a", 0, 1, 0, 0, 3, 2, 0, 0);
 442         SimpleTimeZone tzA = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 3, 2, 0, 0);
 443         // tzb differs from tza
 444         SimpleTimeZone tzb = new SimpleTimeZone(0, "b", 0, 1, 0, 0, 3, 1, 0, 0);
 445         if (tz1.useDaylightTime() || tz2.useDaylightTime() ||
 446             !tza.useDaylightTime() || !tzA.useDaylightTime() ||
 447             !tzb.useDaylightTime()) {
 448             fail("Test is broken -- rewrite it");
 449         }
 450         if (!tza.hasSameRules(tzA) || tza.hasSameRules(tzb)) {
 451             fail("Fail: hasSameRules() broken for zones with rules");
 452         }
 453         if (!tz1.hasSameRules(tz2)) {
 454             fail("Fail: hasSameRules() returns false for zones without rules");
 455             fail("zone 1 = " + tz1);
 456             fail("zone 2 = " + tz2);
 457         }
 458     }
 459 
 460     /**
 461      * SimpleTimeZone constructors, setStartRule(), and setEndRule() don't
 462      * check for out-of-range arguments.
 463      */
 464     @Test
 465     public void Test4154542() {
 466         final int GOOD = 1;
 467         final int BAD  = 0;
 468 
 469         final int GOOD_MONTH       = Calendar.JANUARY;
 470         final int GOOD_DAY         = 1;
 471         final int GOOD_DAY_OF_WEEK = Calendar.SUNDAY;
 472         final int GOOD_TIME        = 0;
 473 
 474         int[] DATA = {
 475             GOOD, Integer.MIN_VALUE,    0,  Integer.MAX_VALUE,   Integer.MIN_VALUE,
 476             GOOD, Calendar.JANUARY,    -5,  Calendar.SUNDAY,     0,
 477             GOOD, Calendar.DECEMBER,    5,  Calendar.SATURDAY,   24*60*60*1000-1,
 478             GOOD, Calendar.DECEMBER,    5,  Calendar.SATURDAY,   24*60*60*1000,
 479             BAD,  Calendar.DECEMBER,    5,  Calendar.SATURDAY,   24*60*60*1000+1,
 480             BAD,  Calendar.DECEMBER,    5,  Calendar.SATURDAY,  -1,
 481             BAD,  Calendar.JANUARY,    -6,  Calendar.SUNDAY,     0,
 482             BAD,  Calendar.DECEMBER,    6,  Calendar.SATURDAY,   24*60*60*1000,
 483             GOOD, Calendar.DECEMBER,    1,  0,                   0,
 484             GOOD, Calendar.DECEMBER,   31,  0,                   0,

 490             GOOD, Calendar.DECEMBER,   31, -Calendar.SATURDAY,   0,
 491             BAD,  Calendar.DECEMBER,   32, -Calendar.SATURDAY,   0,
 492             BAD,  Calendar.DECEMBER,  -32, -Calendar.SATURDAY,   0,
 493             BAD,  Calendar.DECEMBER,   31, -Calendar.SATURDAY-1, 0,
 494         };
 495         SimpleTimeZone zone = new SimpleTimeZone(0, "Z");
 496         for (int i=0; i<DATA.length; i+=5) {
 497             boolean shouldBeGood = (DATA[i] == GOOD);
 498             int month     = DATA[i+1];
 499             int day       = DATA[i+2];
 500             int dayOfWeek = DATA[i+3];
 501             int time      = DATA[i+4];
 502 
 503             Exception ex = null;
 504             try {
 505                 zone.setStartRule(month, day, dayOfWeek, time);
 506             } catch (IllegalArgumentException e) {
 507                 ex = e;
 508             }
 509             if ((ex == null) != shouldBeGood) {
 510                 fail("setStartRule(month=" + month + ", day=" + day +
 511                       ", dayOfWeek=" + dayOfWeek + ", time=" + time +
 512                       (shouldBeGood ? (") should work but throws " + ex)
 513                        : ") should fail but doesn't"));
 514             }
 515 
 516             ex = null;
 517             try {
 518                 zone.setEndRule(month, day, dayOfWeek, time);
 519             } catch (IllegalArgumentException e) {
 520                 ex = e;
 521             }
 522             if ((ex == null) != shouldBeGood) {
 523                 fail("setEndRule(month=" + month + ", day=" + day +
 524                       ", dayOfWeek=" + dayOfWeek + ", time=" + time +
 525                       (shouldBeGood ? (") should work but throws " + ex)
 526                        : ") should fail but doesn't"));
 527             }
 528 
 529             ex = null;
 530             try {
 531                 SimpleTimeZone temp = new SimpleTimeZone(0, "Z",
 532                         month, day, dayOfWeek, time,
 533                         GOOD_MONTH, GOOD_DAY, GOOD_DAY_OF_WEEK, GOOD_TIME);
 534             } catch (IllegalArgumentException e) {
 535                 ex = e;
 536             }
 537             if ((ex == null) != shouldBeGood) {
 538                 fail("SimpleTimeZone(month=" + month + ", day=" + day +
 539                       ", dayOfWeek=" + dayOfWeek + ", time=" + time +
 540                       (shouldBeGood ? (", <end>) should work but throws " + ex)
 541                        : ", <end>) should fail but doesn't"));
 542             }
 543 
 544             ex = null;
 545             try {
 546                 SimpleTimeZone temp = new SimpleTimeZone(0, "Z",
 547                         GOOD_MONTH, GOOD_DAY, GOOD_DAY_OF_WEEK, GOOD_TIME,
 548                         month, day, dayOfWeek, time);
 549             } catch (IllegalArgumentException e) {
 550                 ex = e;
 551             }
 552             if ((ex == null) != shouldBeGood) {
 553                 fail("SimpleTimeZone(<start>, month=" + month + ", day=" + day +
 554                       ", dayOfWeek=" + dayOfWeek + ", time=" + time +
 555                       (shouldBeGood ? (") should work but throws " + ex)
 556                        : ") should fail but doesn't"));
 557             }
 558         }
 559     }
 560 
 561     /**
 562      * SimpleTimeZone.getOffset accepts illegal arguments.
 563      */
 564     @Test
 565     public void Test4154650() {
 566         final int GOOD=1, BAD=0;
 567         final int GOOD_ERA=GregorianCalendar.AD, GOOD_YEAR=1998, GOOD_MONTH=Calendar.AUGUST;
 568         final int GOOD_DAY=2, GOOD_DOW=Calendar.SUNDAY, GOOD_TIME=16*3600000;
 569         int[] DATA = {
 570             GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
 571 
 572             GOOD, GregorianCalendar.BC, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
 573             GOOD, GregorianCalendar.AD, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
 574             BAD,  GregorianCalendar.BC-1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
 575             BAD,  GregorianCalendar.AD+1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
 576 
 577             GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, GOOD_DAY, GOOD_DOW, GOOD_TIME,
 578             GOOD, GOOD_ERA, GOOD_YEAR, Calendar.DECEMBER, GOOD_DAY, GOOD_DOW, GOOD_TIME,
 579             BAD,  GOOD_ERA, GOOD_YEAR, Calendar.JANUARY-1, GOOD_DAY, GOOD_DOW, GOOD_TIME,
 580             BAD,  GOOD_ERA, GOOD_YEAR, Calendar.DECEMBER+1, GOOD_DAY, GOOD_DOW, GOOD_TIME,
 581 
 582             GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 1, GOOD_DOW, GOOD_TIME,
 583             GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 31, GOOD_DOW, GOOD_TIME,
 584             BAD,  GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 0, GOOD_DOW, GOOD_TIME,

 589             BAD,  GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SUNDAY-1, GOOD_TIME,
 590             BAD,  GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SATURDAY+1, GOOD_TIME,
 591 
 592             GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 0,
 593             GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000-1,
 594             BAD,  GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, -1,
 595             BAD,  GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000,
 596         };
 597 
 598         TimeZone tz = TimeZone.getDefault();
 599         for (int i=0; i<DATA.length; i+=7) {
 600             boolean good = DATA[i] == GOOD;
 601             IllegalArgumentException e = null;
 602             try {
 603                 int offset = tz.getOffset(DATA[i+1], DATA[i+2], DATA[i+3],
 604                                           DATA[i+4], DATA[i+5], DATA[i+6]);
 605            } catch (IllegalArgumentException ex) {
 606                 e = ex;
 607             }
 608             if (good != (e == null)) {
 609                 fail("Fail: getOffset(" +
 610                       DATA[i+1] + ", " + DATA[i+2] + ", " + DATA[i+3] + ", " +
 611                       DATA[i+4] + ", " + DATA[i+5] + ", " + DATA[i+6] +
 612                       (good ? (") threw " + e) : ") accepts invalid args"));
 613             }
 614         }
 615     }
 616 
 617     /**
 618      * TimeZone constructors allow null IDs.
 619      */
 620     @Test
 621     public void Test4159922() {
 622         TimeZone z = null;
 623 
 624         // TimeZone API.  Only hasSameRules() and setDefault() should
 625         // allow null.
 626         try {
 627             z = TimeZone.getTimeZone((String)null);
 628             fail("FAIL: Null allowed in getTimeZone");
 629         } catch (NullPointerException e) {}
 630         z = TimeZone.getTimeZone("GMT");
 631         try {
 632             z.getDisplayName(false, TimeZone.SHORT, null);
 633             fail("FAIL: Null allowed in getDisplayName(3)");
 634         } catch (NullPointerException e) {}
 635         try {
 636             z.getDisplayName(null);
 637             fail("FAIL: Null allowed in getDisplayName(1)");
 638         } catch (NullPointerException e) {}
 639         try {
 640             if (z.hasSameRules(null)) {
 641                 fail("FAIL: hasSameRules returned true");
 642             }
 643         } catch (NullPointerException e) {
 644             fail("FAIL: Null NOT allowed in hasSameRules");
 645         }
 646         try {
 647             z.inDaylightTime(null);
 648             fail("FAIL: Null allowed in inDaylightTime");
 649         } catch (NullPointerException e) {}
 650         try {
 651             z.setID(null);
 652             fail("FAIL: Null allowed in setID");
 653         } catch (NullPointerException e) {}
 654 
 655         TimeZone save = TimeZone.getDefault();
 656         try {
 657             TimeZone.setDefault(null);
 658         } catch (NullPointerException e) {
 659             fail("FAIL: Null NOT allowed in setDefault");
 660         } finally {
 661             TimeZone.setDefault(save);
 662         }
 663 
 664         // SimpleTimeZone API
 665         SimpleTimeZone s = null;
 666         try {
 667             s = new SimpleTimeZone(0, null);
 668             fail("FAIL: Null allowed in SimpleTimeZone(2)");
 669         } catch (NullPointerException e) {}
 670         try {
 671             s = new SimpleTimeZone(0, null, 0, 1, 0, 0, 0, 1, 0, 0);
 672             fail("FAIL: Null allowed in SimpleTimeZone(10)");
 673         } catch (NullPointerException e) {}
 674         try {
 675             s = new SimpleTimeZone(0, null, 0, 1, 0, 0, 0, 1, 0, 0, 1000);
 676             fail("FAIL: Null allowed in SimpleTimeZone(11)");
 677         } catch (NullPointerException e) {}
 678     }
 679 
 680     /**
 681      * TimeZone broken at midnight.  The TimeZone code fails to handle
 682      * transitions at midnight correctly.
 683      */
 684     @SuppressWarnings("deprecation")
 685     @Test
 686     public void Test4162593() {
 687         SimpleDateFormat fmt = new SimpleDateFormat("z", Locale.US);
 688         final int ONE_HOUR = 60*60*1000;
 689         TimeZone initialZone = TimeZone.getDefault();
 690 
 691         SimpleTimeZone asuncion = new SimpleTimeZone(-4*ONE_HOUR, "America/Asuncion" /*PY%sT*/,
 692             Calendar.OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR,
 693             Calendar.MARCH, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR);
 694 
 695         /* Zone
 696          * Starting time
 697          * Transition expected between start+1H and start+2H
 698          */
 699         Object[] DATA = {
 700             new SimpleTimeZone(2*ONE_HOUR, "Asia/Damascus" /*EE%sT*/,
 701                 Calendar.APRIL, 1, 0 /*DOM*/, 0*ONE_HOUR,
 702                 Calendar.OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR),
 703             new int[] {98, Calendar.SEPTEMBER, 30, 22, 0},
 704             Boolean.TRUE,
 705 

 708             Boolean.FALSE,
 709 
 710             asuncion,
 711             new int[] {100, Calendar.FEBRUARY, 29, 22, 0},
 712             Boolean.TRUE,
 713         };
 714 
 715         String[] zone = new String[4];
 716 
 717         try {
 718             for (int j=0; j<DATA.length; j+=3) {
 719                 TimeZone tz = (TimeZone)DATA[j];
 720                 TimeZone.setDefault(tz);
 721                 fmt.setTimeZone(tz);
 722 
 723                 // Must construct the Date object AFTER setting the default zone
 724                 int[] p = (int[])DATA[j+1];
 725                 Date d = new Date(p[0], p[1], p[2], p[3], p[4]);
 726                 boolean transitionExpected = ((Boolean)DATA[j+2]).booleanValue();
 727 
 728                 System.out.println(tz.getID() + ":");
 729                 for (int i=0; i<4; ++i) {
 730                     zone[i] = fmt.format(d);
 731                     System.out.println("" + i + ": " + d);
 732                     d = new Date(d.getTime() + ONE_HOUR);
 733                 }
 734                 if (zone[0].equals(zone[1]) &&
 735                     (zone[1].equals(zone[2]) != transitionExpected) &&
 736                     zone[2].equals(zone[3])) {
 737                     System.out.println("Ok: transition " + transitionExpected);
 738                 } else {
 739                     fail("Fail: boundary transition incorrect");
 740                 }
 741             }
 742         }
 743         finally {
 744             // restore the initial time zone so that this test case
 745             // doesn't affect the others.
 746             TimeZone.setDefault(initialZone);
 747         }
 748     }
 749 
 750     /**
 751      * TimeZone broken in last hour of year
 752      */
 753     @Test
 754     public void Test4173604() {
 755         // test both SimpleTimeZone and ZoneInfo objects.
 756         // @since 1.4
 757         sub4173604(getPST());
 758         sub4173604(TimeZone.getTimeZone("PST"));
 759     }
 760 
 761     private void sub4173604(TimeZone pst) {
 762         int o22 = pst.getOffset(1, 1998, 11, 31, Calendar.THURSDAY, 22*60*60*1000);
 763         int o23 = pst.getOffset(1, 1998, 11, 31, Calendar.THURSDAY, 23*60*60*1000);
 764         int o00 = pst.getOffset(1, 1999, 0, 1, Calendar.FRIDAY, 0);
 765         if (o22 != o23 || o22 != o00) {
 766             fail("Offsets should be the same (for PST), but got: " +
 767                   "12/31 22:00 " + o22 +
 768                   ", 12/31 23:00 " + o23 +
 769                   ", 01/01 00:00 " + o00);
 770         }
 771 
 772         GregorianCalendar cal = new GregorianCalendar();
 773         cal.setTimeZone(pst);
 774         cal.clear();
 775         cal.set(1998, Calendar.JANUARY, 1);
 776         int lastDST = cal.get(Calendar.DST_OFFSET);
 777         int transitions = 0;
 778         int delta = 5;
 779         while (cal.get(Calendar.YEAR) < 2000) {
 780             cal.add(Calendar.MINUTE, delta);
 781             if (cal.get(Calendar.DST_OFFSET) != lastDST) {
 782                 ++transitions;
 783                 Calendar t = (Calendar)cal.clone();
 784                 t.add(Calendar.MINUTE, -delta);
 785                 System.out.println(t.getTime() + "  " + t.get(Calendar.DST_OFFSET));
 786                 System.out.println(cal.getTime() + "  " + (lastDST=cal.get(Calendar.DST_OFFSET)));
 787             }
 788         }
 789         if (transitions != 4) {
 790             fail("Saw " + transitions + " transitions; should have seen 4");
 791         }
 792     }
 793 
 794     /**
 795      * getDisplayName doesn't work with unusual savings/offsets.
 796      */
 797     @SuppressWarnings("deprecation")
 798     @Test
 799     public void Test4176686() {
 800         // Construct a zone that does not observe DST but
 801         // that does have a DST savings (which should be ignored).
 802         int offset = 90 * 60000; // 1:30
 803         SimpleTimeZone z1 = new SimpleTimeZone(offset, "_std_zone_");
 804         z1.setDSTSavings(45 * 60000); // 0:45
 805 
 806         // Construct a zone that observes DST for the first 6 months.
 807         SimpleTimeZone z2 = new SimpleTimeZone(offset, "_dst_zone_");
 808         z2.setDSTSavings(45 * 60000); // 0:45
 809         z2.setStartRule(Calendar.JANUARY, 1, 0);
 810         z2.setEndRule(Calendar.JULY, 1, 0);
 811 
 812         // Also check DateFormat
 813         DateFormat fmt1 = new SimpleDateFormat("z");
 814         fmt1.setTimeZone(z1); // Format uses standard zone
 815         DateFormat fmt2 = new SimpleDateFormat("z");
 816         fmt2.setTimeZone(z2); // Format uses DST zone
 817         Date dst = new Date(1970-1900, Calendar.FEBRUARY, 1); // Time in DST
 818         Date std = new Date(1970-1900, Calendar.AUGUST, 1); // Time in standard

 826             "getDisplayName(true, SHORT)/std zone",
 827             z1.getDisplayName(true, TimeZone.SHORT), "GMT+01:30",
 828             "getDisplayName(true, LONG)/std zone",
 829             z1.getDisplayName(true, TimeZone.LONG ), "GMT+01:30",
 830             "getDisplayName(false, SHORT)/dst zone",
 831             z2.getDisplayName(false, TimeZone.SHORT), "GMT+01:30",
 832             "getDisplayName(false, LONG)/dst zone",
 833             z2.getDisplayName(false, TimeZone.LONG ), "GMT+01:30",
 834             "getDisplayName(true, SHORT)/dst zone",
 835             z2.getDisplayName(true, TimeZone.SHORT), "GMT+02:15",
 836             "getDisplayName(true, LONG)/dst zone",
 837             z2.getDisplayName(true, TimeZone.LONG ), "GMT+02:15",
 838             "DateFormat.format(std)/std zone", fmt1.format(std), "GMT+01:30",
 839             "DateFormat.format(dst)/std zone", fmt1.format(dst), "GMT+01:30",
 840             "DateFormat.format(std)/dst zone", fmt2.format(std), "GMT+01:30",
 841             "DateFormat.format(dst)/dst zone", fmt2.format(dst), "GMT+02:15",
 842         };
 843 
 844         for (int i=0; i<DATA.length; i+=3) {
 845             if (!DATA[i+1].equals(DATA[i+2])) {
 846                 fail("FAIL: " + DATA[i] + " -> " + DATA[i+1] + ", exp " + DATA[i+2]);
 847             }
 848         }
 849     }
 850 
 851     /**
 852      * SimpleTimeZone allows invalid DOM values.
 853      */
 854     @Test
 855     public void Test4184229() {
 856         SimpleTimeZone zone = null;
 857         try {
 858             zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0);
 859             fail("Failed. No exception has been thrown for DOM -1 startDay");
 860         } catch(IllegalArgumentException e) {
 861             System.out.println("(a) " + e.getMessage());
 862         }
 863         try {
 864             zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0);
 865             fail("Failed. No exception has been thrown for DOM -1 endDay");
 866         } catch(IllegalArgumentException e) {
 867             System.out.println("(b) " + e.getMessage());
 868         }
 869         try {
 870             zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0, 1000);
 871             fail("Failed. No exception has been thrown for DOM -1 startDay +savings");
 872         } catch(IllegalArgumentException e) {
 873             System.out.println("(c) " + e.getMessage());
 874         }
 875         try {
 876             zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0, 1000);
 877             fail("Failed. No exception has been thrown for DOM -1 endDay +savings");
 878         } catch(IllegalArgumentException e) {
 879             System.out.println("(d) " + e.getMessage());
 880         }
 881         // Make a valid constructor call for subsequent tests.
 882         zone = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 0, 1, 0, 0);
 883         try {
 884             zone.setStartRule(0, -1, 0, 0);
 885             fail("Failed. No exception has been thrown for DOM -1 setStartRule +savings");
 886         } catch(IllegalArgumentException e) {
 887             System.out.println("(e) " + e.getMessage());
 888         }
 889         try {
 890             zone.setStartRule(0, -1, 0);
 891             fail("Failed. No exception has been thrown for DOM -1 setStartRule");
 892         } catch(IllegalArgumentException e) {
 893             System.out.println("(f) " + e.getMessage());
 894         }
 895         try {
 896             zone.setEndRule(0, -1, 0, 0);
 897             fail("Failed. No exception has been thrown for DOM -1 setEndRule +savings");
 898         } catch(IllegalArgumentException e) {
 899             System.out.println("(g) " + e.getMessage());
 900         }
 901         try {
 902             zone.setEndRule(0, -1, 0);
 903             fail("Failed. No exception has been thrown for DOM -1 setEndRule");
 904         } catch(IllegalArgumentException e) {
 905             System.out.println("(h) " + e.getMessage());
 906         }
 907     }
 908 
 909     /**
 910      * SimpleTimeZone.getOffset() throws IllegalArgumentException when to get
 911      * of 2/29/1996 (leap day).
 912      */
 913     @Test
 914     public void Test4208960 () {
 915         // test both SimpleTimeZone and ZoneInfo objects.
 916         // @since 1.4
 917         sub4208960(getPST());
 918         sub4208960(TimeZone.getTimeZone("PST"));
 919     }
 920 
 921     private void sub4208960(TimeZone tz) {
 922         try {
 923             int offset = tz.getOffset(GregorianCalendar.AD, 1996, Calendar.FEBRUARY, 29,
 924                                       Calendar.THURSDAY, 0);
 925         } catch (IllegalArgumentException e) {
 926             fail("FAILED: to get TimeZone.getOffset(2/29/96)");
 927         }
 928         try {
 929             int offset = tz.getOffset(GregorianCalendar.AD, 1997, Calendar.FEBRUARY, 29,
 930                                       Calendar.THURSDAY, 0);
 931             fail("FAILED: TimeZone.getOffset(2/29/97) expected to throw Exception.");
 932         } catch (IllegalArgumentException e) {
 933             System.out.println("got IllegalArgumentException");
 934         }
 935     }
 936 
 937     /**
 938      * 4966229: java.util.Date methods may works incorrect.
 939      * sun.util.calendar.ZoneInfo doesn't clone properly.
 940      */
 941     @SuppressWarnings("deprecation")
 942     @Test
 943     public void Test4966229() {
 944         TimeZone savedTZ = TimeZone.getDefault();
 945         try {
 946             TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
 947             Date d = new Date(2100-1900, 5, 1); // specify year >2037
 948             TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
 949 
 950             Calendar cal = new GregorianCalendar(tz);
 951             cal.setTime(d);
 952 
 953             // Change the raw offset in tz
 954             int offset = tz.getRawOffset();
 955             tz.setRawOffset(0);
 956 
 957             TimeZone tz2 = (TimeZone) tz.clone();
 958             Calendar cal2 = new GregorianCalendar(tz2);
 959             cal2.setTime(d);
 960             int expectedHourOfDay = cal2.get(cal.HOUR_OF_DAY);
 961 
 962             // Restore the GMT offset in tz which shouldn't affect tz2
 963             tz.setRawOffset(offset);
 964             cal2.setTime(d);
 965             int hourOfDay = cal2.get(cal.HOUR_OF_DAY);
 966             if (hourOfDay != expectedHourOfDay) {
 967                 fail("wrong hour of day: got: " + hourOfDay
 968                       + ", expected: " + expectedHourOfDay);
 969             }
 970         } finally {
 971             TimeZone.setDefault(savedTZ);
 972         }
 973     }
 974 
 975     /**
 976      * 6433179: (tz) Incorrect DST end for America/Winnipeg and Canada/Central in 2038+
 977      */
 978     @Test
 979     public void Test6433179() {
 980         // Use the old America/Winnipeg rule for testing. Note that
 981         // startMode is WALL_TIME for testing. It's actually
 982         // STANDARD_TIME, though.
 983         //Rule  Winn    1966    2005    -       Oct     lastSun 2:00s   0       S
 984         //Rule  Winn    1987    2005    -       Apr     Sun>=1  2:00s   1:00    D
 985         TimeZone tz = new SimpleTimeZone(-6*ONE_HOUR, "America/Winnipeg",
 986           Calendar.APRIL, 1, -Calendar.SUNDAY, 2*ONE_HOUR, SimpleTimeZone.WALL_TIME,
 987           Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME,
 988           1*ONE_HOUR);
 989         Calendar cal = Calendar.getInstance(tz, Locale.US);
 990         cal.clear();
 991         cal.set(2039, Calendar.OCTOBER, 1);
 992         cal.getTime();
 993         cal.set(cal.DAY_OF_WEEK, cal.SUNDAY);
 994         cal.set(cal.DAY_OF_WEEK_IN_MONTH, -1);
 995         cal.add(Calendar.HOUR_OF_DAY, 2);
 996         if (cal.get(cal.DST_OFFSET) == 0) {
 997             fail("Should still be in DST.");
 998         }
 999     }
1000 
1001     private static final int ONE_HOUR = 60 * 60 * 1000;
1002     /**
1003      * Returns an instance of SimpleTimeZone for
1004      * "PST". (TimeZone.getTimeZone() no longer returns a
1005      * SimpleTimeZone object.)
1006      * @since 1.4
1007      */
1008     private SimpleTimeZone getPST() {
1009         return new SimpleTimeZone(-8*ONE_HOUR, "PST",
1010                                   Calendar.APRIL, 1, -Calendar.SUNDAY, 2*ONE_HOUR,
1011                                   Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*ONE_HOUR,
1012                                   1*ONE_HOUR);
1013     }
1014 }
1015 //eof
< prev index next >