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 4031502 4035301 4040996 4051765 4059654 4061476 4070502 4071197 4071385
  27  * 4073929 4083167 4086724 4092362 4095407 4096231 4096539 4100311 4103271
  28  * 4106136 4108764 4114578 4118384 4125881 4125892 4136399 4141665 4142933
  29  * 4145158 4145983 4147269 4149677 4162587 4165343 4166109 4167060 4173516
  30  * 4174361 4177484 4197699 4209071 4288792 4328747 4413980 4546637 4623997
  31  * 4685354 4655637 4683492 4080631 4080631 4167995 4340146 4639407
  32  * 4652815 4652830 4740554 4936355 4738710 4633646 4846659 4822110 4960642
  33  * 4973919 4980088 4965624 5013094 5006864 8152077
  34  * @library /java/text/testlib
  35  */
  36 
  37 import java.lang.reflect.*;
  38 import java.io.*;
  39 import java.util.*;
  40 import java.text.*;
  41 
  42 public class CalendarRegression extends IntlTest {
  43 
  44     public static void main(String[] args) throws Exception {
  45         new CalendarRegression().run(args);
  46     }
  47 
  48     /*
  49       Synopsis: java.sql.Timestamp constructor works wrong on Windows 95
  50 
  51       ==== Here is the test ====
  52       public static void main (String args[]) {
  53         java.sql.Timestamp t= new java.sql.Timestamp(0,15,5,5,8,13,123456700);
  54         logln("expected=1901-04-05 05:08:13.1234567");
  55         logln(" result="+t);
  56       }
  57 
  58       ==== Here is the output of the test on Solaris or NT ====
  59       expected=1901-04-05 05:08:13.1234567
  60       result=1901-04-05 05:08:13.1234567
  61 
  62       ==== Here is the output of the test on Windows95 ====
  63       expected=1901-04-05 05:08:13.1234567
  64       result=1901-04-05 06:08:13.1234567
  65       */
  66 
  67     public void Test4031502() {
  68         // This bug actually occurs on Windows NT as well, and doesn't
  69         // require the host zone to be set; it can be set in Java.
  70         String[] ids = TimeZone.getAvailableIDs();
  71         boolean bad = false;
  72         for (int i=0; i<ids.length; ++i) {
  73             TimeZone zone = TimeZone.getTimeZone(ids[i]);
  74             GregorianCalendar cal = new GregorianCalendar(zone);
  75             cal.clear();
  76             cal.set(1900, 15, 5, 5, 8, 13);
  77             if (cal.get(Calendar.HOUR) != 5) {
  78                 logln(zone.getID() + " " +
  79                                    //zone.useDaylightTime() + " " +
  80                                    cal.get(Calendar.DST_OFFSET) / (60*60*1000) + " " +
  81                                    zone.getRawOffset() / (60*60*1000) +
  82                                    ": HOUR = " + cal.get(Calendar.HOUR));
  83                 bad = true;
  84             }
  85         }
  86         if (bad) errln("TimeZone problems with GC");
  87     }
  88 
  89     public void Test4035301() {
  90         GregorianCalendar c = new GregorianCalendar(98, 8, 7);
  91         GregorianCalendar d = new GregorianCalendar(98, 8, 7);
  92         if (c.after(d) ||
  93             c.after(c) ||
  94             c.before(d) ||
  95             c.before(c) ||
  96             !c.equals(c) ||
  97             !c.equals(d))
  98             errln("Fail");
  99     }
 100 
 101     public void Test4040996() {
 102         String[] ids = TimeZone.getAvailableIDs(-8 * 60 * 60 * 1000);
 103         SimpleTimeZone pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, ids[0]);
 104         pdt.setStartRule(Calendar.APRIL, 1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
 105         pdt.setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
 106         Calendar calendar = new GregorianCalendar(pdt);
 107 
 108         calendar.set(Calendar.MONTH,3);
 109         calendar.set(Calendar.DAY_OF_MONTH,18);
 110         calendar.set(Calendar.SECOND, 30);
 111 
 112         logln("MONTH: " + calendar.get(Calendar.MONTH));
 113         logln("DAY_OF_MONTH: " +
 114                            calendar.get(Calendar.DAY_OF_MONTH));
 115         logln("MINUTE: " + calendar.get(Calendar.MINUTE));
 116         logln("SECOND: " + calendar.get(Calendar.SECOND));
 117 
 118         calendar.add(Calendar.SECOND,6);
 119         //This will print out todays date for MONTH and DAY_OF_MONTH
 120         //instead of the date it was set to.
 121         //This happens when adding MILLISECOND or MINUTE also
 122         logln("MONTH: " + calendar.get(Calendar.MONTH));
 123         logln("DAY_OF_MONTH: " +
 124                            calendar.get(Calendar.DAY_OF_MONTH));
 125         logln("MINUTE: " + calendar.get(Calendar.MINUTE));
 126         logln("SECOND: " + calendar.get(Calendar.SECOND));
 127         if (calendar.get(Calendar.MONTH) != 3 ||
 128             calendar.get(Calendar.DAY_OF_MONTH) != 18 ||
 129             calendar.get(Calendar.SECOND) != 36)
 130             errln("Fail: Calendar.add misbehaves");
 131     }
 132 
 133     public void Test4051765() {
 134         Calendar cal = Calendar.getInstance();
 135         cal.setLenient(false);
 136         cal.set(Calendar.DAY_OF_WEEK, 0);
 137         try {
 138             cal.getTime();
 139             errln("Fail: DAY_OF_WEEK 0 should be disallowed");
 140         }
 141         catch (IllegalArgumentException e) {
 142             return;
 143         }
 144     }
 145 
 146     /* User error - no bug here
 147     public void Test4059524() {
 148         // Create calendar for April 10, 1997
 149         GregorianCalendar calendar  = new GregorianCalendar();
 150         // print out a bunch of interesting things
 151         logln("ERA: " + calendar.get(calendar.ERA));
 152         logln("YEAR: " + calendar.get(calendar.YEAR));
 153         logln("MONTH: " + calendar.get(calendar.MONTH));
 154         logln("WEEK_OF_YEAR: " +
 155                            calendar.get(calendar.WEEK_OF_YEAR));
 156         logln("WEEK_OF_MONTH: " +
 157                            calendar.get(calendar.WEEK_OF_MONTH));
 158         logln("DATE: " + calendar.get(calendar.DATE));
 159         logln("DAY_OF_MONTH: " +
 160                            calendar.get(calendar.DAY_OF_MONTH));
 161         logln("DAY_OF_YEAR: " + calendar.get(calendar.DAY_OF_YEAR));
 162         logln("DAY_OF_WEEK: " + calendar.get(calendar.DAY_OF_WEEK));
 163         logln("DAY_OF_WEEK_IN_MONTH: " +
 164                            calendar.get(calendar.DAY_OF_WEEK_IN_MONTH));
 165         logln("AM_PM: " + calendar.get(calendar.AM_PM));
 166         logln("HOUR: " + calendar.get(calendar.HOUR));
 167         logln("HOUR_OF_DAY: " + calendar.get(calendar.HOUR_OF_DAY));
 168         logln("MINUTE: " + calendar.get(calendar.MINUTE));
 169         logln("SECOND: " + calendar.get(calendar.SECOND));
 170         logln("MILLISECOND: " + calendar.get(calendar.MILLISECOND));
 171         logln("ZONE_OFFSET: "
 172                            + (calendar.get(calendar.ZONE_OFFSET)/(60*60*1000)));
 173         logln("DST_OFFSET: "
 174                            + (calendar.get(calendar.DST_OFFSET)/(60*60*1000)));
 175         calendar  = new GregorianCalendar(1997,3,10);
 176         calendar.getTime();
 177         logln("April 10, 1997");
 178         logln("ERA: " + calendar.get(calendar.ERA));
 179         logln("YEAR: " + calendar.get(calendar.YEAR));
 180         logln("MONTH: " + calendar.get(calendar.MONTH));
 181         logln("WEEK_OF_YEAR: " +
 182                            calendar.get(calendar.WEEK_OF_YEAR));
 183         logln("WEEK_OF_MONTH: " +
 184                            calendar.get(calendar.WEEK_OF_MONTH));
 185         logln("DATE: " + calendar.get(calendar.DATE));
 186         logln("DAY_OF_MONTH: " +
 187                            calendar.get(calendar.DAY_OF_MONTH));
 188         logln("DAY_OF_YEAR: " + calendar.get(calendar.DAY_OF_YEAR));
 189         logln("DAY_OF_WEEK: " + calendar.get(calendar.DAY_OF_WEEK));
 190         logln("DAY_OF_WEEK_IN_MONTH: " + calendar.get(calendar.DAY_OF_WEEK_IN_MONTH));
 191         logln("AM_PM: " + calendar.get(calendar.AM_PM));
 192         logln("HOUR: " + calendar.get(calendar.HOUR));
 193         logln("HOUR_OF_DAY: " + calendar.get(calendar.HOUR_OF_DAY));
 194         logln("MINUTE: " + calendar.get(calendar.MINUTE));
 195         logln("SECOND: " + calendar.get(calendar.SECOND));
 196         logln("MILLISECOND: " + calendar.get(calendar.MILLISECOND));
 197         logln("ZONE_OFFSET: "
 198                            + (calendar.get(calendar.ZONE_OFFSET)/(60*60*1000))); // in hours
 199         logln("DST_OFFSET: "
 200                            + (calendar.get(calendar.DST_OFFSET)/(60*60*1000))); // in hours
 201     }
 202     */
 203 
 204     public void Test4059654() {
 205         GregorianCalendar gc = new GregorianCalendar();
 206 
 207         gc.set(1997, 3, 1, 15, 16, 17); // April 1, 1997
 208 
 209         gc.set(Calendar.HOUR, 0);
 210         gc.set(Calendar.AM_PM, Calendar.AM);
 211         gc.set(Calendar.MINUTE, 0);
 212         gc.set(Calendar.SECOND, 0);
 213         gc.set(Calendar.MILLISECOND, 0);
 214 
 215         Date cd = gc.getTime();
 216         Date exp = new Date(97, 3, 1, 0, 0, 0);
 217         if (!cd.equals(exp))
 218             errln("Fail: Calendar.set broken. Got " + cd + " Want " + exp);
 219     }
 220 
 221     public void Test4061476() {
 222         SimpleDateFormat fmt = new SimpleDateFormat("ddMMMyy", Locale.UK);
 223         Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT"),
 224                                                      Locale.UK);
 225         fmt.setCalendar(cal);
 226         try
 227             {
 228                 Date date = fmt.parse("29MAY97");
 229                 cal.setTime(date);
 230             }
 231         catch (Exception e) {;}
 232         cal.set(Calendar.HOUR_OF_DAY, 13);
 233         logln("Hour: "+cal.get(Calendar.HOUR_OF_DAY));
 234         cal.add(Calendar.HOUR_OF_DAY, 6);
 235         logln("Hour: "+cal.get(Calendar.HOUR_OF_DAY));
 236         if (cal.get(Calendar.HOUR_OF_DAY) != 19)
 237             errln("Fail: Want 19 Got " + cal.get(Calendar.HOUR_OF_DAY));
 238     }
 239 
 240     public void Test4070502() {
 241         Date d = getAssociatedDate(new Date(98, 0, 30));
 242         Calendar cal = new GregorianCalendar();
 243         cal.setTime(d);
 244         if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY ||
 245             cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY)
 246             errln("Fail: Want weekday Got " + d);
 247     }
 248 
 249     /**
 250      * Get the associated date starting from a specified date
 251      * NOTE: the unnecessary "getTime()'s" below are a work-around for a
 252      * bug in jdk 1.1.3 (and probably earlier versions also)
 253      * <p>
 254      * @param date The date to start from
 255      */
 256     public static Date getAssociatedDate(Date d) {
 257         GregorianCalendar cal = new GregorianCalendar();
 258         cal.setTime(d);
 259         //cal.add(field, amount); //<-- PROBLEM SEEN WITH field = DATE,MONTH
 260         // cal.getTime();  // <--- REMOVE THIS TO SEE BUG
 261         while (true) {
 262             int wd = cal.get(Calendar.DAY_OF_WEEK);
 263             if (wd == Calendar.SATURDAY || wd == Calendar.SUNDAY) {
 264                 cal.add(Calendar.DATE, 1);
 265                 // cal.getTime();
 266             }
 267             else
 268                 break;
 269         }
 270         return cal.getTime();
 271     }
 272 
 273     public void Test4071197() {
 274         dowTest(false);
 275         dowTest(true);
 276     }
 277 
 278     void dowTest(boolean lenient) {
 279         GregorianCalendar cal = new GregorianCalendar();
 280         cal.set(1997, Calendar.AUGUST, 12); // Wednesday
 281         // cal.getTime(); // Force update
 282         cal.setLenient(lenient);
 283         cal.set(1996, Calendar.DECEMBER, 1); // Set the date to be December 1, 1996
 284         int dow = cal.get(Calendar.DAY_OF_WEEK);
 285         int min = cal.getMinimum(Calendar.DAY_OF_WEEK);
 286         int max = cal.getMaximum(Calendar.DAY_OF_WEEK);
 287         logln(cal.getTime().toString());
 288         if (min != Calendar.SUNDAY || max != Calendar.SATURDAY)
 289             errln("FAIL: Min/max bad");
 290         if (dow < min || dow > max)
 291             errln("FAIL: Day of week " + dow + " out of range");
 292         if (dow != Calendar.SUNDAY)
 293             errln("FAIL: Day of week should be SUNDAY Got " + dow);
 294     }
 295 
 296     public void Test4071385() {
 297         Calendar cal = Calendar.getInstance();
 298         cal.setTime(new Date(98, Calendar.JUNE, 24));
 299         cal.set(Calendar.MONTH, Calendar.NOVEMBER); // change a field
 300         logln(cal.getTime().toString());
 301         if (!cal.getTime().equals(new Date(98, Calendar.NOVEMBER, 24)))
 302             errln("Fail");
 303     }
 304 
 305     public void Test4073929() {
 306         GregorianCalendar foo1 = new GregorianCalendar(1997, 8, 27);
 307         foo1.add(Calendar.DAY_OF_MONTH, +1);
 308         int testyear = foo1.get(Calendar.YEAR);
 309         int testmonth = foo1.get(Calendar.MONTH);
 310         int testday = foo1.get(Calendar.DAY_OF_MONTH);
 311         if (testyear != 1997 ||
 312             testmonth != 8 ||
 313             testday != 28)
 314             errln("Fail: Calendar not initialized");
 315     }
 316 
 317     public void Test4083167() {
 318         TimeZone saveZone = TimeZone.getDefault();
 319         try {
 320             TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
 321             Date firstDate = new Date();
 322             Calendar cal = new GregorianCalendar();
 323             cal.setTime(firstDate);
 324             long firstMillisInDay = cal.get(Calendar.HOUR_OF_DAY) * 3600000L +
 325                                     cal.get(Calendar.MINUTE) * 60000L +
 326                                     cal.get(Calendar.SECOND) * 1000L +
 327                                     cal.get(Calendar.MILLISECOND);
 328 
 329             logln("Current time: " + firstDate.toString());
 330 
 331             for (int validity=0; validity<30; validity++) {
 332                 Date lastDate = new Date(firstDate.getTime() +
 333                                          (long)validity*1000*24*60*60);
 334                 cal.setTime(lastDate);
 335                 long millisInDay = cal.get(Calendar.HOUR_OF_DAY) * 3600000L +
 336                                    cal.get(Calendar.MINUTE) * 60000L +
 337                                    cal.get(Calendar.SECOND) * 1000L +
 338                                    cal.get(Calendar.MILLISECOND);
 339                 if (firstMillisInDay != millisInDay) {
 340                     errln("Day has shifted " + lastDate);
 341                 }
 342             }
 343         }
 344         finally {
 345             TimeZone.setDefault(saveZone);
 346         }
 347     }
 348 
 349     public void Test4086724() {
 350         SimpleDateFormat date;
 351         TimeZone saveZone = TimeZone.getDefault();
 352         Locale saveLocale = Locale.getDefault();
 353 
 354         String summerTime = "British Summer Time";
 355         String standardTime = "Greenwich Mean Time";
 356         try {
 357             Locale.setDefault(Locale.UK);
 358             TimeZone.setDefault(TimeZone.getTimeZone("Europe/London"));
 359             date = new SimpleDateFormat("zzzz");
 360 
 361             Calendar cal=Calendar.getInstance();
 362             cal.set(1997,Calendar.SEPTEMBER,30);
 363             Date now=cal.getTime();
 364             String formattedDate = date.format(now);
 365             if (!formattedDate.equals(summerTime)) {
 366                 errln("Wrong display name \"" + formattedDate
 367                       + "\" for <" + now + ">");
 368             }
 369             int weekOfYear = cal.get(Calendar.WEEK_OF_YEAR);
 370             if (weekOfYear != 40) {
 371                 errln("Wrong week-of-year " + weekOfYear
 372                       + " for <" + now + ">");
 373             }
 374 
 375             cal.set(1996,Calendar.DECEMBER,31);
 376             now=cal.getTime();
 377             formattedDate = date.format(now);
 378             if (!formattedDate.equals(standardTime)) {
 379                 errln("Wrong display name \"" + formattedDate
 380                       + "\" for <" + now + ">");
 381             }
 382             weekOfYear = cal.get(Calendar.WEEK_OF_YEAR);
 383             if (weekOfYear != 1) {
 384                 errln("Wrong week-of-year " + weekOfYear
 385                       + " for <" + now + ">");
 386             }
 387 
 388             cal.set(1997,Calendar.JANUARY,1);
 389             now=cal.getTime();
 390             formattedDate = date.format(now);
 391             if (!formattedDate.equals(standardTime)) {
 392                 errln("Wrong display name \"" + formattedDate
 393                       + "\" for <" + now + ">");
 394             }
 395             weekOfYear = cal.get(Calendar.WEEK_OF_YEAR);
 396             if (weekOfYear != 1) {
 397                 errln("Wrong week-of-year " + weekOfYear
 398                       + " for <" + now + ">");
 399             }
 400 
 401             cal.set(1997,Calendar.JANUARY,8);
 402             now=cal.getTime();
 403             formattedDate = date.format(now);
 404             if (!formattedDate.equals(standardTime)) {
 405                 errln("Wrong display name \"" + formattedDate
 406                       + "\" for <" + now + ">");
 407             }
 408             weekOfYear = cal.get(Calendar.WEEK_OF_YEAR);
 409             if (weekOfYear != 2) {
 410                 errln("Wrong week-of-year " + weekOfYear
 411                       + " for <" + now + ">");
 412             }
 413 
 414         }
 415         finally {
 416             Locale.setDefault(saveLocale);
 417             TimeZone.setDefault(saveZone);
 418         }
 419     }
 420 
 421     public void Test4092362() {
 422         GregorianCalendar cal1 = new GregorianCalendar(1997, 10, 11, 10, 20, 40);
 423         /*cal1.set( Calendar.YEAR, 1997 );
 424         cal1.set( Calendar.MONTH, 10 );
 425         cal1.set( Calendar.DATE, 11 );
 426         cal1.set( Calendar.HOUR, 10 );
 427         cal1.set( Calendar.MINUTE, 20 );
 428         cal1.set( Calendar.SECOND, 40 ); */
 429 
 430         logln( " Cal1 = " + cal1.getTime().getTime() );
 431         logln( " Cal1 time in ms = " + cal1.get(Calendar.MILLISECOND) );
 432         for( int k = 0; k < 100 ; k++ );
 433 
 434         GregorianCalendar cal2 = new GregorianCalendar(1997, 10, 11, 10, 20, 40);
 435         /*cal2.set( Calendar.YEAR, 1997 );
 436         cal2.set( Calendar.MONTH, 10 );
 437         cal2.set( Calendar.DATE, 11 );
 438         cal2.set( Calendar.HOUR, 10 );
 439         cal2.set( Calendar.MINUTE, 20 );
 440         cal2.set( Calendar.SECOND, 40 ); */
 441 
 442         logln( " Cal2 = " + cal2.getTime().getTime() );
 443         logln( " Cal2 time in ms = " + cal2.get(Calendar.MILLISECOND) );
 444         if( !cal1.equals( cal2 ) )
 445             errln("Fail: Milliseconds randomized");
 446     }
 447 
 448     public void Test4095407() {
 449         GregorianCalendar a = new GregorianCalendar(1997,Calendar.NOVEMBER, 13);
 450         int dow = a.get(Calendar.DAY_OF_WEEK);
 451         if (dow != Calendar.THURSDAY)
 452             errln("Fail: Want THURSDAY Got " + dow);
 453     }
 454 
 455     public void Test4096231() {
 456         TimeZone GMT = TimeZone.getTimeZone("GMT");
 457         TimeZone PST = TimeZone.getTimeZone("PST");
 458         int sec = 0, min = 0, hr = 0, day = 1, month = 10, year = 1997;
 459 
 460         Calendar cal1 = new GregorianCalendar(PST);
 461         cal1.setTime(new Date(880698639000L));
 462         int p;
 463         logln("PST 1 is: " + (p=cal1.get(cal1.HOUR_OF_DAY)));
 464         cal1.setTimeZone(GMT);
 465         // Issue 1: Changing the timezone doesn't change the
 466         //          represented time.
 467         int h1,h2;
 468         logln("GMT 1 is: " + (h1=cal1.get(cal1.HOUR_OF_DAY)));
 469         cal1.setTime(new Date(880698639000L));
 470         logln("GMT 2 is: " + (h2=cal1.get(cal1.HOUR_OF_DAY)));
 471         // Note: This test had a bug in it.  It wanted h1!=h2, when
 472         // what was meant was h1!=p.  Fixed this concurrent with fix
 473         // to 4177484.
 474         if (p == h1 || h1 != h2)
 475             errln("Fail: Hour same in different zones");
 476 
 477         Calendar cal2 = new GregorianCalendar(GMT);
 478         Calendar cal3 = new GregorianCalendar(PST);
 479         cal2.set(Calendar.MILLISECOND, 0);
 480         cal3.set(Calendar.MILLISECOND, 0);
 481 
 482         cal2.set(cal1.get(cal1.YEAR),
 483                  cal1.get(cal1.MONTH),
 484                  cal1.get(cal1.DAY_OF_MONTH),
 485                  cal1.get(cal1.HOUR_OF_DAY),
 486                  cal1.get(cal1.MINUTE),
 487                  cal1.get(cal1.SECOND));
 488 
 489         long t1,t2,t3,t4;
 490         logln("RGMT 1 is: " + (t1=cal2.getTime().getTime()));
 491         cal3.set(year, month, day, hr, min, sec);
 492         logln("RPST 1 is: " + (t2=cal3.getTime().getTime()));
 493         cal3.setTimeZone(GMT);
 494         logln("RGMT 2 is: " + (t3=cal3.getTime().getTime()));
 495         cal3.set(cal1.get(cal1.YEAR),
 496                  cal1.get(cal1.MONTH),
 497                  cal1.get(cal1.DAY_OF_MONTH),
 498                  cal1.get(cal1.HOUR_OF_DAY),
 499                  cal1.get(cal1.MINUTE),
 500                  cal1.get(cal1.SECOND));
 501         // Issue 2: Calendar continues to use the timezone in its
 502         //          constructor for set() conversions, regardless
 503         //          of calls to setTimeZone()
 504         logln("RGMT 3 is: " + (t4=cal3.getTime().getTime()));
 505         if (t1 == t2 ||
 506             t1 != t4 ||
 507             t2 != t3)
 508             errln("Fail: Calendar zone behavior faulty");
 509     }
 510 
 511     public void Test4096539() {
 512         int[] y = {31,28,31,30,31,30,31,31,30,31,30,31};
 513 
 514         for (int x=0;x<12;x++) {
 515             GregorianCalendar gc = new
 516                 GregorianCalendar(1997,x,y[x]);
 517             int m1,m2;
 518             log((m1=gc.get(Calendar.MONTH)+1)+"/"+
 519                              gc.get(Calendar.DATE)+"/"+gc.get(Calendar.YEAR)+
 520                              " + 1mo = ");
 521 
 522             gc.add(Calendar.MONTH, 1);
 523             logln((m2=gc.get(Calendar.MONTH)+1)+"/"+
 524                                gc.get(Calendar.DATE)+"/"+gc.get(Calendar.YEAR)
 525                                );
 526             int m = (m1 % 12) + 1;
 527             if (m2 != m)
 528                 errln("Fail: Want " + m + " Got " + m2);
 529         }
 530 
 531     }
 532 
 533     public void Test4100311() {
 534         GregorianCalendar cal = (GregorianCalendar)Calendar.getInstance();
 535         cal.set(Calendar.YEAR, 1997);
 536         cal.set(Calendar.DAY_OF_YEAR, 1);
 537         Date d = cal.getTime();             // Should be Jan 1
 538         logln(d.toString());
 539         if (cal.get(Calendar.DAY_OF_YEAR) != 1)
 540             errln("Fail: DAY_OF_YEAR not set");
 541     }
 542 
 543     public void Test4103271() {
 544         if (Locale.getDefault().equals(new Locale("th", "TH"))) {
 545             return;
 546         }
 547 
 548         SimpleDateFormat sdf = new SimpleDateFormat();
 549         int numYears=40, startYear=1997, numDays=15;
 550         String output, testDesc;
 551         GregorianCalendar testCal = (GregorianCalendar)Calendar.getInstance();
 552         testCal.clear();
 553         sdf.setCalendar(testCal);
 554         sdf.applyPattern("d MMM yyyy");
 555         boolean fail = false;
 556         for (int firstDay=1; firstDay<=2; firstDay++) {
 557             for (int minDays=1; minDays<=7; minDays++) {
 558                 testCal.setMinimalDaysInFirstWeek(minDays);
 559                 testCal.setFirstDayOfWeek(firstDay);
 560                 testDesc = ("Test" + String.valueOf(firstDay) + String.valueOf(minDays));
 561                 logln(testDesc + " => 1st day of week=" +
 562                                    String.valueOf(firstDay) +
 563                                    ", minimum days in first week=" +
 564                                    String.valueOf(minDays));
 565                 for (int j=startYear; j<=startYear+numYears; j++) {
 566                     testCal.set(j,11,25);
 567                     for(int i=0; i<numDays; i++) {
 568                         testCal.add(Calendar.DATE,1);
 569                         String calWOY;
 570                         int actWOY = testCal.get(Calendar.WEEK_OF_YEAR);
 571                         if (actWOY < 1 || actWOY > 53) {
 572                             Date d = testCal.getTime();
 573                             calWOY = String.valueOf(actWOY);
 574                             output = testDesc + " - " + sdf.format(d) + "\t";
 575                             output = output + "\t" + calWOY;
 576                             logln(output);
 577                             fail = true;
 578                         }
 579                     }
 580                 }
 581             }
 582         }
 583 
 584         int[] DATA = {
 585             3, 52, 52, 52, 52, 52, 52, 52,
 586                 1,  1,  1,  1,  1,  1,  1,
 587                 2,  2,  2,  2,  2,  2,  2,
 588             4, 52, 52, 52, 52, 52, 52, 52,
 589                53, 53, 53, 53, 53, 53, 53,
 590                 1,  1,  1,  1,  1,  1,  1,
 591         };
 592         testCal.setFirstDayOfWeek(Calendar.SUNDAY);
 593         for (int j=0; j<DATA.length; j+=22) {
 594             logln("Minimal days in first week = " + DATA[j] +
 595                                "  Week starts on Sunday");
 596             testCal.setMinimalDaysInFirstWeek(DATA[j]);
 597             testCal.set(1997, Calendar.DECEMBER, 21);
 598             for (int i=0; i<21; ++i) {
 599                 int woy = testCal.get(Calendar.WEEK_OF_YEAR);
 600                 log("\t" + testCal.getTime() + " " + woy);
 601                 if (woy != DATA[j + 1 + i]) {
 602                     log(" ERROR");
 603                     fail = true;
 604                 } else {
 605                     logln(" OK");
 606                 }
 607 
 608                 // Now compute the time from the fields, and make sure we
 609                 // get the same answer back.  This is a round-trip test.
 610                 Date save = testCal.getTime();
 611                 testCal.clear();
 612                 testCal.set(Calendar.YEAR, DATA[j+1+i] < 25 ? 1998 : 1997);
 613                 testCal.set(Calendar.WEEK_OF_YEAR, DATA[j+1+i]);
 614                 testCal.set(Calendar.DAY_OF_WEEK, (i%7) + Calendar.SUNDAY);
 615                 if (!testCal.getTime().equals(save)) {
 616                     logln("  Parse failed: " + testCal.getTime());
 617                     fail= true;
 618                 } else {
 619                     logln("  Passed");
 620                 }
 621 
 622                 testCal.setTime(save);
 623                 testCal.add(Calendar.DAY_OF_MONTH, 1);
 624             }
 625         }
 626 
 627         // Test field disambiguation with a few special hard-coded cases.
 628         // This shouldn't fail if the above cases aren't failing.
 629         Object[] DISAM = {
 630             new Integer(1998), new Integer(1), new Integer(Calendar.SUNDAY),
 631                 new Date(97, Calendar.DECEMBER, 28),
 632             new Integer(1998), new Integer(2), new Integer(Calendar.SATURDAY),
 633                 new Date(98, Calendar.JANUARY, 10),
 634             new Integer(1998), new Integer(53), new Integer(Calendar.THURSDAY),
 635                 new Date(98, Calendar.DECEMBER, 31),
 636             new Integer(1998), new Integer(53), new Integer(Calendar.FRIDAY),
 637                 new Date(99, Calendar.JANUARY, 1),
 638         };
 639         testCal.setMinimalDaysInFirstWeek(3);
 640         testCal.setFirstDayOfWeek(Calendar.SUNDAY);
 641         for (int i=0; i<DISAM.length; i+=4) {
 642             int y = ((Integer)DISAM[i]).intValue();
 643             int woy = ((Integer)DISAM[i+1]).intValue();
 644             int dow = ((Integer)DISAM[i+2]).intValue();
 645             Date exp = (Date)DISAM[i+3];
 646             testCal.clear();
 647             testCal.set(Calendar.YEAR, y);
 648             testCal.set(Calendar.WEEK_OF_YEAR, woy);
 649             testCal.set(Calendar.DAY_OF_WEEK, dow);
 650             log(y + "-W" + woy + "-DOW" + dow);
 651             if (!testCal.getTime().equals(exp)) {
 652                 logln("  FAILED expect: " + exp + "\n            got: " +testCal.getTime());
 653                 fail = true;
 654             } else {
 655                 logln("  OK");
 656             }
 657         }
 658 
 659         // Now try adding and rolling
 660         Object ADD = new Object();
 661         Object ROLL = new Object();
 662         Object[] ADDROLL = {
 663             ADD, new Integer(1), new Date(98, Calendar.DECEMBER, 25), new Date(99, Calendar.JANUARY, 1),
 664             ADD, new Integer(1), new Date(97, Calendar.DECEMBER, 28), new Date(98, Calendar.JANUARY, 4),
 665             ROLL, new Integer(1), new Date(98, Calendar.DECEMBER, 27), new Date(98, Calendar.JANUARY, 4),
 666             ROLL, new Integer(1), new Date(99, Calendar.DECEMBER, 24), new Date(99, Calendar.DECEMBER, 31),
 667             ROLL, new Integer(1), new Date(99, Calendar.DECEMBER, 25), new Date(99, Calendar.JANUARY, 9),
 668         };
 669         testCal.setMinimalDaysInFirstWeek(3);
 670         testCal.setFirstDayOfWeek(Calendar.SUNDAY);
 671         for (int i=0; i<ADDROLL.length; i+=4) {
 672             int amount = ((Integer)ADDROLL[i+1]).intValue();
 673             Date before = (Date)ADDROLL[i+2];
 674             Date after = (Date)ADDROLL[i+3];
 675 
 676             testCal.setTime(before);
 677             if (ADDROLL[i] == ADD)
 678                 testCal.add(Calendar.WEEK_OF_YEAR, amount);
 679             else
 680                 testCal.roll(Calendar.WEEK_OF_YEAR, amount);
 681             log((ADDROLL[i]==ADD ? "add(WOY," : "roll(WOY,") +
 682                 amount + ")\t     " + before +
 683                 "\n\t\t  => " + testCal.getTime());
 684             if (!after.equals(testCal.getTime())) {
 685                 logln("\tFAIL\n\t\texp: " + after);
 686                 fail = true;
 687             } else
 688                 logln("  OK");
 689 
 690             testCal.setTime(after);
 691             if (ADDROLL[i] == ADD)
 692                 testCal.add(Calendar.WEEK_OF_YEAR, -amount);
 693             else
 694                 testCal.roll(Calendar.WEEK_OF_YEAR, -amount);
 695             log((ADDROLL[i]==ADD ? "add(WOY," : "roll(WOY,") +
 696                 (-amount) + ")     " + after +
 697                 "\n\t\t  => " + testCal.getTime());
 698             if (!before.equals(testCal.getTime())) {
 699                 logln("\tFAIL\n\t\texp: " + before);
 700                 fail = true;
 701             }
 702             else logln("\tOK");
 703         }
 704 
 705         if (fail) {
 706             errln("Fail: Week of year misbehaving");
 707         }
 708     }
 709 
 710     public void Test4106136() {
 711         Locale saveLocale = Locale.getDefault();
 712         try {
 713             Locale[] locales = { Locale.CHINESE, Locale.CHINA };
 714             for (int i=0; i<locales.length; ++i) {
 715                 Locale.setDefault(locales[i]);
 716                 int[] n = {
 717                     Calendar.getAvailableLocales().length,
 718                     DateFormat.getAvailableLocales().length,
 719                     NumberFormat.getAvailableLocales().length
 720                 };
 721                 for (int j=0; j<n.length; ++j) {
 722                     if (n[j] == 0) {
 723                         errln("Fail: No locales for " + locales[i]);
 724                     }
 725                 }
 726             }
 727         }
 728         finally {
 729             Locale.setDefault(saveLocale);
 730         }
 731     }
 732 
 733     public void Test4108764() {
 734         Date d00 = new Date(97, Calendar.MARCH, 15, 12, 00, 00);
 735         Date d01 = new Date(97, Calendar.MARCH, 15, 12, 00, 56);
 736         Date d10 = new Date(97, Calendar.MARCH, 15, 12, 34, 00);
 737         Date d11 = new Date(97, Calendar.MARCH, 15, 12, 34, 56);
 738         Date epoch = new Date(70, Calendar.JANUARY, 1);
 739 
 740         Calendar cal = Calendar.getInstance();
 741         cal.setTime(d11);
 742 
 743         cal.clear( Calendar.MINUTE );
 744         logln(cal.getTime().toString());
 745         if (!cal.getTime().equals(d01))
 746             errln("Fail: clear(MINUTE) broken");
 747 
 748         cal.set( Calendar.SECOND, 0 );
 749         logln(cal.getTime().toString());
 750         if (!cal.getTime().equals(d00))
 751             errln("Fail: set(SECOND, 0) broken");
 752 
 753         cal.setTime(d11);
 754         cal.set( Calendar.SECOND, 0 );
 755         logln(cal.getTime().toString());
 756         if (!cal.getTime().equals(d10))
 757             errln("Fail: set(SECOND, 0) broken #2");
 758 
 759         cal.clear( Calendar.MINUTE );
 760         logln(cal.getTime().toString());
 761         if (!cal.getTime().equals(d00))
 762             errln("Fail: clear(MINUTE) broken #2");
 763 
 764         cal.clear();
 765         logln(cal.getTime().toString());
 766         if (!cal.getTime().equals(epoch))
 767             errln("Fail: clear() broken Want " + epoch);
 768     }
 769 
 770     public void Test4114578() {
 771         int ONE_HOUR = 60*60*1000;
 772         TimeZone saveZone = TimeZone.getDefault();
 773         boolean fail = false;
 774         try {
 775             TimeZone.setDefault(TimeZone.getTimeZone("PST"));
 776             Calendar cal = Calendar.getInstance();
 777             long onset = new Date(98, Calendar.APRIL, 5, 1, 0).getTime() + ONE_HOUR;
 778             long cease = new Date(98, Calendar.OCTOBER, 25, 0, 0).getTime() + 2*ONE_HOUR;
 779 
 780             final int ADD = 1;
 781             final int ROLL = 2;
 782 
 783             long[] DATA = {
 784                 // Start            Action   Amt    Expected_change
 785                 onset - ONE_HOUR,   ADD,      1,     ONE_HOUR,
 786                 onset,              ADD,     -1,    -ONE_HOUR,
 787                 onset - ONE_HOUR,   ROLL,     1,     ONE_HOUR,
 788                 onset,              ROLL,    -1,    -ONE_HOUR,
 789                 cease - ONE_HOUR,   ADD,      1,     ONE_HOUR,
 790                 cease,              ADD,     -1,    -ONE_HOUR,
 791                 // roll() was changed to support wall-clock-based roll (JDK-8152077). The
 792                 // time value may jump 2 hours by skipping non-existent wall-clock time.
 793                 // Note that JDK-4114578 was a problem of add(), not roll().
 794                 cease - ONE_HOUR,   ROLL,     1,     ONE_HOUR * 2,
 795                 cease,              ROLL,    -1,    -ONE_HOUR * 2,
 796             };
 797 
 798             for (int i=0; i<DATA.length; i+=4) {
 799                 Date date = new Date(DATA[i]);
 800                 int amt = (int) DATA[i+2];
 801                 long expectedChange = DATA[i+3];
 802 
 803                 log(date.toString());
 804                 cal.setTime(date);
 805 
 806                 switch ((int) DATA[i+1]) {
 807                 case ADD:
 808                     log(" add (HOUR," + (amt<0?"":"+")+amt + ")= ");
 809                     cal.add(Calendar.HOUR, amt);
 810                     break;
 811                 case ROLL:
 812                     log(" roll(HOUR," + (amt<0?"":"+")+amt + ")= ");
 813                     cal.roll(Calendar.HOUR, amt);
 814                     break;
 815                 }
 816 
 817                 log(cal.getTime().toString());
 818 
 819                 long change = cal.getTime().getTime() - date.getTime();
 820                 if (change != expectedChange) {
 821                     fail = true;
 822                     logln(" FAIL");
 823                 }
 824                 else logln(" OK");
 825             }
 826         } finally {
 827             TimeZone.setDefault(saveZone);
 828         }
 829 
 830         if (fail) {
 831             errln("Fail: roll/add misbehaves around DST onset/cease");
 832         }
 833     }
 834 
 835     /**
 836      * Make sure maximum for HOUR field is 11, not 12.
 837      */
 838     public void Test4118384() {
 839         Calendar cal = Calendar.getInstance();
 840         if (cal.getMaximum(Calendar.HOUR) != 11 ||
 841             cal.getLeastMaximum(Calendar.HOUR) != 11 ||
 842             cal.getActualMaximum(Calendar.HOUR) != 11)
 843             errln("Fail: maximum of HOUR field should be 11");
 844     }
 845 
 846     /**
 847      * Check isLeapYear for BC years.
 848      */
 849     public void Test4125881() {
 850         GregorianCalendar cal = (GregorianCalendar) Calendar.getInstance();
 851         DateFormat fmt = new SimpleDateFormat("MMMM d, yyyy G");
 852         cal.clear();
 853         for (int y=-20; y<=10; ++y) {
 854             cal.set(Calendar.ERA, y < 1 ? GregorianCalendar.BC : GregorianCalendar.AD);
 855             cal.set(Calendar.YEAR, y < 1 ? 1 - y : y);
 856             logln(y + " = " + fmt.format(cal.getTime()) + " " +
 857                                cal.isLeapYear(y));
 858             if (cal.isLeapYear(y) != ((y+40)%4 == 0))
 859                 errln("Leap years broken");
 860         }
 861     }
 862 
 863     /**
 864      * Prove that GregorianCalendar is proleptic (it used to cut off
 865      * at 45 BC, and not have leap years before then).
 866      */
 867     public void Test4125892() {
 868         if (Locale.getDefault().equals(new Locale("th", "TH"))) {
 869             return;
 870         }
 871 
 872         GregorianCalendar cal = (GregorianCalendar) Calendar.getInstance();
 873         DateFormat fmt = new SimpleDateFormat("MMMM d, yyyy G");
 874         cal.clear();
 875         cal.set(Calendar.ERA, GregorianCalendar.BC);
 876         cal.set(Calendar.YEAR, 81); // 81 BC is a leap year (proleptically)
 877         cal.set(Calendar.MONTH, Calendar.FEBRUARY);
 878         cal.set(Calendar.DATE, 28);
 879         cal.add(Calendar.DATE, 1);
 880         if (cal.get(Calendar.DATE) != 29 ||
 881             !cal.isLeapYear(-80)) // -80 == 81 BC
 882             errln("Calendar not proleptic");
 883     }
 884 
 885     /**
 886      * Calendar and GregorianCalendar hashCode() methods need improvement.
 887      * Calendar needs a good implementation that subclasses can override,
 888      * and GregorianCalendar should use that implementation.
 889      */
 890     public void Test4136399() {
 891         /* Note: This test is actually more strict than it has to be.
 892          * Technically, there is no requirement that unequal objects have
 893          * unequal hashes.  We only require equal objects to have equal hashes.
 894          * It is desirable for unequal objects to have distributed hashes, but
 895          * there is no hard requirement here.
 896          *
 897          * In this test we make assumptions about certain attributes of calendar
 898          * objects getting represented in the hash, which need not always be the
 899          * case (although it does work currently with the given test). */
 900         Calendar a = Calendar.getInstance();
 901         Calendar b = (Calendar)a.clone();
 902         if (a.hashCode() != b.hashCode()) {
 903             errln("Calendar hash code unequal for cloned objects");
 904         }
 905 
 906         b.setMinimalDaysInFirstWeek(7 - a.getMinimalDaysInFirstWeek());
 907         if (a.hashCode() == b.hashCode()) {
 908             errln("Calendar hash code ignores minimal days in first week");
 909         }
 910         b.setMinimalDaysInFirstWeek(a.getMinimalDaysInFirstWeek());
 911 
 912         b.setFirstDayOfWeek((a.getFirstDayOfWeek() % 7) + 1); // Next day
 913         if (a.hashCode() == b.hashCode()) {
 914             errln("Calendar hash code ignores first day of week");
 915         }
 916         b.setFirstDayOfWeek(a.getFirstDayOfWeek());
 917 
 918         b.setLenient(!a.isLenient());
 919         if (a.hashCode() == b.hashCode()) {
 920             errln("Calendar hash code ignores lenient setting");
 921         }
 922         b.setLenient(a.isLenient());
 923 
 924         // Assume getTimeZone() returns a reference, not a clone
 925         // of a reference -- this is true as of this writing
 926         b.getTimeZone().setRawOffset(a.getTimeZone().getRawOffset() + 60*60*1000);
 927         if (a.hashCode() == b.hashCode()) {
 928             errln("Calendar hash code ignores zone");
 929         }
 930         b.getTimeZone().setRawOffset(a.getTimeZone().getRawOffset());
 931 
 932         GregorianCalendar c = new GregorianCalendar();
 933         GregorianCalendar d = (GregorianCalendar)c.clone();
 934         if (c.hashCode() != d.hashCode()) {
 935             errln("GregorianCalendar hash code unequal for clones objects");
 936         }
 937         Date cutover = c.getGregorianChange();
 938         d.setGregorianChange(new Date(cutover.getTime() + 24*60*60*1000));
 939         if (c.hashCode() == d.hashCode()) {
 940             errln("GregorianCalendar hash code ignores cutover");
 941         }
 942     }
 943 
 944     /**
 945      * GregorianCalendar.equals() ignores cutover date
 946      */
 947     public void Test4141665() {
 948         GregorianCalendar cal = new GregorianCalendar();
 949         GregorianCalendar cal2 = (GregorianCalendar)cal.clone();
 950         Date cut = cal.getGregorianChange();
 951         Date cut2 = new Date(cut.getTime() + 100*24*60*60*1000L); // 100 days later
 952         if (!cal.equals(cal2)) {
 953             errln("Cloned GregorianCalendars not equal");
 954         }
 955         cal2.setGregorianChange(cut2);
 956         if (cal.equals(cal2)) {
 957             errln("GregorianCalendar.equals() ignores cutover");
 958         }
 959     }
 960 
 961     /**
 962      * Bug states that ArrayIndexOutOfBoundsException is thrown by GregorianCalendar.roll()
 963      * when IllegalArgumentException should be.
 964      */
 965     public void Test4142933() {
 966         GregorianCalendar calendar = new GregorianCalendar();
 967         try {
 968             calendar.roll(-1, true);
 969             errln("Test failed, no exception trown");
 970         }
 971         catch (IllegalArgumentException e) {
 972             // OK: Do nothing
 973             // logln("Test passed");
 974         }
 975         catch (Exception e) {
 976             errln("Test failed. Unexpected exception is thrown: " + e);
 977             e.printStackTrace();
 978         }
 979     }
 980 
 981     /**
 982      * GregorianCalendar handling of Dates Long.MIN_VALUE and Long.MAX_VALUE is
 983      * confusing; unless the time zone has a raw offset of zero, one or the
 984      * other of these will wrap.  We've modified the test given in the bug
 985      * report to therefore only check the behavior of a calendar with a zero raw
 986      * offset zone.
 987      */
 988     public void Test4145158() {
 989         GregorianCalendar calendar = new GregorianCalendar();
 990 
 991         calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
 992 
 993         calendar.setTime(new Date(Long.MIN_VALUE));
 994         int year1 = calendar.get(Calendar.YEAR);
 995         int era1 = calendar.get(Calendar.ERA);
 996 
 997         calendar.setTime(new Date(Long.MAX_VALUE));
 998         int year2 = calendar.get(Calendar.YEAR);
 999         int era2 = calendar.get(Calendar.ERA);
1000 
1001         if (year1 == year2 && era1 == era2) {
1002             errln("Fail: Long.MIN_VALUE or Long.MAX_VALUE wrapping around");
1003         }
1004     }
1005 
1006     /**
1007      * Maximum value for YEAR field wrong.
1008      */
1009     public void Test4145983() {
1010         GregorianCalendar calendar = new GregorianCalendar();
1011         calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
1012         Date[] DATES = { new Date(Long.MAX_VALUE), new Date(Long.MIN_VALUE) };
1013         for (int i=0; i<DATES.length; ++i) {
1014             calendar.setTime(DATES[i]);
1015             int year = calendar.get(Calendar.YEAR);
1016             int maxYear = calendar.getMaximum(Calendar.YEAR);
1017             if (year > maxYear) {
1018                 errln("Failed for "+DATES[i].getTime()+" ms: year=" +
1019                       year + ", maxYear=" + maxYear);
1020             }
1021         }
1022     }
1023 
1024     /**
1025      * This is a bug in the validation code of GregorianCalendar.  As reported,
1026      * the bug seems worse than it really is, due to a bug in the way the bug
1027      * report test was written.  In reality the bug is restricted to the DAY_OF_YEAR
1028      * field. - liu 6/29/98
1029      */
1030     public void Test4147269() {
1031         final String[] fieldName = {
1032             "ERA",
1033             "YEAR",
1034             "MONTH",
1035             "WEEK_OF_YEAR",
1036             "WEEK_OF_MONTH",
1037             "DAY_OF_MONTH",
1038             "DAY_OF_YEAR",
1039             "DAY_OF_WEEK",
1040             "DAY_OF_WEEK_IN_MONTH",
1041             "AM_PM",
1042             "HOUR",
1043             "HOUR_OF_DAY",
1044             "MINUTE",
1045             "SECOND",
1046             "MILLISECOND",
1047             "ZONE_OFFSET",
1048             "DST_OFFSET"
1049         };
1050         GregorianCalendar calendar = new GregorianCalendar();
1051         calendar.setLenient(false);
1052         Date date = new Date(1996-1900, Calendar.JANUARY, 3); // Arbitrary date
1053         for (int field = 0; field < Calendar.FIELD_COUNT; field++) {
1054             calendar.setTime(date);
1055             // Note: In the bug report, getActualMaximum() was called instead
1056             // of getMaximum() -- this was an error.  The validation code doesn't
1057             // use getActualMaximum(), since that's too costly.
1058             int max = calendar.getMaximum(field);
1059             int value = max+1;
1060             calendar.set(field, value);
1061             try {
1062                 calendar.getTime(); // Force time computation
1063                 // We expect an exception to be thrown. If we fall through
1064                 // to the next line, then we have a bug.
1065                 errln("Test failed with field " + fieldName[field] +
1066                       ", date before: " + date +
1067                       ", date after: " + calendar.getTime() +
1068                       ", value: " + value + " (max = " + max +")");
1069             } catch (IllegalArgumentException e) {}
1070         }
1071     }
1072 
1073     /**
1074      * Reported bug is that a GregorianCalendar with a cutover of Date(Long.MAX_VALUE)
1075      * doesn't behave as a pure Julian calendar.
1076      * CANNOT REPRODUCE THIS BUG
1077      */
1078     public void Test4149677() {
1079         TimeZone[] zones = { TimeZone.getTimeZone("GMT"),
1080                              TimeZone.getTimeZone("PST"),
1081                              TimeZone.getTimeZone("EAT") };
1082         for (int i=0; i<zones.length; ++i) {
1083             GregorianCalendar calendar = new GregorianCalendar(zones[i]);
1084 
1085             // Make sure extreme values don't wrap around
1086             calendar.setTime(new Date(Long.MIN_VALUE));
1087             if (calendar.get(Calendar.ERA) != GregorianCalendar.BC) {
1088                 errln("Fail: Date(Long.MIN_VALUE) has an AD year in " + zones[i]);
1089             }
1090             calendar.setTime(new Date(Long.MAX_VALUE));
1091             if (calendar.get(Calendar.ERA) != GregorianCalendar.AD) {
1092                 errln("Fail: Date(Long.MAX_VALUE) has a BC year in " + zones[i]);
1093             }
1094 
1095             calendar.setGregorianChange(new Date(Long.MAX_VALUE));
1096             // to obtain a pure Julian calendar
1097 
1098             boolean is100Leap = calendar.isLeapYear(100);
1099             if (!is100Leap) {
1100                 errln("test failed with zone " + zones[i].getID());
1101                 errln(" cutover date is Date(Long.MAX_VALUE)");
1102                 errln(" isLeapYear(100) returns: " + is100Leap);
1103             }
1104         }
1105     }
1106 
1107     /**
1108      * Calendar and Date HOUR broken.  If HOUR is out-of-range, Calendar
1109      * and Date classes will misbehave.
1110      */
1111     public void Test4162587() {
1112         TimeZone savedTz = TimeZone.getDefault();
1113         TimeZone tz = TimeZone.getTimeZone("PST");
1114         TimeZone.setDefault(tz);
1115         GregorianCalendar cal = new GregorianCalendar(tz);
1116         Date d;
1117 
1118         try {
1119             for (int i=0; i<5; ++i) {
1120                 if (i>0) logln("---");
1121 
1122                 cal.clear();
1123                 cal.set(1998, Calendar.APRIL, 5, i, 0);
1124                 d = cal.getTime();
1125                 String s0 = d.toString();
1126                 logln("0 " + i + ": " + s0);
1127 
1128                 cal.clear();
1129                 cal.set(1998, Calendar.APRIL, 4, i+24, 0);
1130                 d = cal.getTime();
1131                 String sPlus = d.toString();
1132                 logln("+ " + i + ": " + sPlus);
1133 
1134                 cal.clear();
1135                 cal.set(1998, Calendar.APRIL, 6, i-24, 0);
1136                 d = cal.getTime();
1137                 String sMinus = d.toString();
1138                 logln("- " + i + ": " + sMinus);
1139 
1140                 if (!s0.equals(sPlus) || !s0.equals(sMinus)) {
1141                     errln("Fail: All three lines must match");
1142                 }
1143             }
1144         }
1145         finally {
1146             TimeZone.setDefault(savedTz);
1147         }
1148     }
1149 
1150     /**
1151      * Adding 12 months behaves differently from adding 1 year
1152      */
1153     public void Test4165343() {
1154         GregorianCalendar calendar = new GregorianCalendar(1996, Calendar.FEBRUARY, 29);
1155         Date start = calendar.getTime();
1156         logln("init date: " + start);
1157         calendar.add(Calendar.MONTH, 12);
1158         Date date1 = calendar.getTime();
1159         logln("after adding 12 months: " + date1);
1160         calendar.setTime(start);
1161         calendar.add(Calendar.YEAR, 1);
1162         Date date2 = calendar.getTime();
1163         logln("after adding one year : " + date2);
1164         if (date1.equals(date2)) {
1165             logln("Test passed");
1166         } else {
1167             errln("Test failed");
1168         }
1169     }
1170 
1171     /**
1172      * GregorianCalendar.getActualMaximum() does not account for first day of week.
1173      */
1174     public void Test4166109() {
1175         /* Test month:
1176          *
1177          *      March 1998
1178          * Su Mo Tu We Th Fr Sa
1179          *  1  2  3  4  5  6  7
1180          *  8  9 10 11 12 13 14
1181          * 15 16 17 18 19 20 21
1182          * 22 23 24 25 26 27 28
1183          * 29 30 31
1184          */
1185         boolean passed = true;
1186         int field = Calendar.WEEK_OF_MONTH;
1187 
1188         GregorianCalendar calendar = new GregorianCalendar(Locale.US);
1189         calendar.set(1998, Calendar.MARCH, 1);
1190         calendar.setMinimalDaysInFirstWeek(1);
1191         logln("Date:  " + calendar.getTime());
1192 
1193         int firstInMonth = calendar.get(Calendar.DAY_OF_MONTH);
1194 
1195         for (int firstInWeek = Calendar.SUNDAY; firstInWeek <= Calendar.SATURDAY; firstInWeek++) {
1196             calendar.setFirstDayOfWeek(firstInWeek);
1197             int returned = calendar.getActualMaximum(field);
1198             int expected = (31 + ((firstInMonth - firstInWeek + 7)% 7) + 6) / 7;
1199 
1200             logln("First day of week = " + firstInWeek +
1201                   "  getActualMaximum(WEEK_OF_MONTH) = " + returned +
1202                   "  expected = " + expected +
1203                   ((returned == expected) ? "  ok" : "  FAIL"));
1204 
1205             if (returned != expected) {
1206                 passed = false;
1207             }
1208         }
1209         if (!passed) {
1210             errln("Test failed");
1211         }
1212     }
1213 
1214     /**
1215      * Calendar.getActualMaximum(YEAR) works wrong.
1216      *
1217      * Note: Before 1.5, this test case assumed that
1218      * setGregorianChange didn't change object's date. But it was
1219      * changed. See 4928615.
1220      */
1221     public void Test4167060() {
1222         int field = Calendar.YEAR;
1223         DateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy G",
1224                                                  Locale.US);
1225 
1226         int[][] dates = {
1227             // year, month, day of month
1228             { 100, Calendar.NOVEMBER, 1 },
1229             { -99 /*100BC*/, Calendar.JANUARY, 1 },
1230             { 1996, Calendar.FEBRUARY, 29 }};
1231 
1232         String[] id = { "Hybrid", "Gregorian", "Julian" };
1233 
1234         for (int k=0; k<3; ++k) {
1235             logln("--- " + id[k] + " ---");
1236 
1237             for (int j = 0; j < dates.length; ++j) {
1238                 GregorianCalendar calendar = new GregorianCalendar();
1239                 if (k == 1) {
1240                     calendar.setGregorianChange(new Date(Long.MIN_VALUE));
1241                 } else if (k == 2) {
1242                     calendar.setGregorianChange(new Date(Long.MAX_VALUE));
1243                 }
1244                 calendar.set(dates[j][0], dates[j][1], dates[j][2]);
1245                 format.setCalendar((Calendar)calendar.clone());
1246 
1247                 Date dateBefore = calendar.getTime();
1248 
1249                 int maxYear = calendar.getActualMaximum(field);
1250                 logln("maxYear: " + maxYear + " for " + format.format(calendar.getTime()));
1251                 logln("date before: " + format.format(dateBefore));
1252 
1253                 int years[] = {2000, maxYear-1, maxYear, maxYear+1};
1254 
1255                 for (int i = 0; i < years.length; i++) {
1256                     boolean valid = years[i] <= maxYear;
1257                     calendar.set(field, years[i]);
1258                     Date dateAfter = calendar.getTime();
1259                     int newYear = calendar.get(field);
1260                     calendar.setTime(dateBefore); // restore calendar for next use
1261 
1262                     logln(" Year " + years[i] + (valid? " ok " : " bad") +
1263                           " => " + format.format(dateAfter));
1264                     if (valid && newYear != years[i]) {
1265                         errln("  FAIL: " + newYear + " should be valid; date, month and time shouldn't change");
1266                     } else if (!valid && newYear == years[i]) {
1267                         errln("  FAIL: " + newYear + " should be invalid");
1268                     }
1269                 }
1270             }
1271         }
1272     }
1273 
1274     /**
1275      * Calendar.roll broken
1276      * This bug relies on the TimeZone bug 4173604 to also be fixed.
1277      */
1278     public void Test4173516() {
1279         if (Locale.getDefault().equals(new Locale("th", "TH"))) {
1280             return;
1281         }
1282 
1283         int fieldsList[][] = {
1284             { 1997, Calendar.FEBRUARY,  1, 10, 45, 15, 900 },
1285             { 1999, Calendar.DECEMBER, 22, 23, 59, 59, 999 },
1286             // test case for 4960642 with default cutover
1287             { 1582, Calendar.OCTOBER,   4, 23, 59, 59, 999 },
1288         };
1289         String[] fieldNames = {
1290             "ERA", "YEAR", "MONTH", "WEEK_OF_YEAR", "WEEK_OF_MONTH",
1291             "DAY_OF_MONTH", "DAY_OF_YEAR", "DAY_OF_WEEK", "DAY_OF_WEEK_IN_MONTH",
1292             "AM_PM", "HOUR", "HOUR_OF_DAY", "MINUTE", "SECOND", "MILLISECOND",
1293             "ZONE_OFFSET", "DST_OFFSET"
1294         };
1295 
1296         Locale savedLocale = Locale.getDefault();
1297         Locale.setDefault(Locale.US);
1298         int limit = 40;
1299 
1300         try {
1301             GregorianCalendar cal = new GregorianCalendar();
1302 
1303             cal.setTime(new Date(0));
1304             cal.roll(Calendar.HOUR,  0x7F000000);
1305             cal.roll(Calendar.HOUR, -0x7F000000);
1306             if (cal.getTime().getTime() != 0) {
1307                 errln("Hour rolling broken. expected 0, got "+cal.getTime().getTime());
1308             }
1309 
1310             for (int op=0; op<2; ++op) {
1311                 logln("Testing GregorianCalendar " + (op==0 ? "add" : "roll"));
1312 
1313                 for (int field=0; field < Calendar.FIELD_COUNT; ++field) {
1314                     if (field != Calendar.ZONE_OFFSET &&
1315                         field != Calendar.DST_OFFSET) {
1316                         for (int j=0; j<fieldsList.length; ++j) {
1317                             int fields[] = fieldsList[j];
1318                             cal.clear();
1319                             cal.set(fields[0], fields[1], fields[2],
1320                                     fields[3], fields[4], fields[5]);
1321                             cal.set(Calendar.MILLISECOND, fields[6]);
1322                             for (int i = 0; i < 2*limit; i++) {
1323                                 if (op == 0) {
1324                                     cal.add(field, i < limit ? 1 : -1);
1325                                 } else {
1326                                     cal.roll(field, i < limit ? 1 : -1);
1327                                 }
1328                             }
1329 
1330                             if (cal.get(Calendar.YEAR) != fields[0] ||
1331                                 cal.get(Calendar.MONTH) != fields[1] ||
1332                                 cal.get(Calendar.DATE) != fields[2] ||
1333                                 cal.get(Calendar.HOUR_OF_DAY) != fields[3] ||
1334                                 cal.get(Calendar.MINUTE) != fields[4] ||
1335                                 cal.get(Calendar.SECOND) != fields[5] ||
1336                                 cal.get(Calendar.MILLISECOND) != fields[6]) {
1337                                 errln("Field " + field +
1338                                       " (" + fieldNames[field] +
1339                                       ") FAIL, expected " +
1340                                       fields[0] +
1341                                       "/" + (fields[1] + 1) +
1342                                       "/" + fields[2] +
1343                                       " " + fields[3] +
1344                                       ":" + fields[4] +
1345                                       ":" + fields[5] +
1346                                       "." + fields[6] +
1347                                       ", got " + cal.get(Calendar.YEAR) +
1348                                       "/" + (cal.get(Calendar.MONTH) + 1) +
1349                                       "/" + cal.get(Calendar.DATE) +
1350                                       " " + cal.get(Calendar.HOUR_OF_DAY) +
1351                                       ":" + cal.get(Calendar.MINUTE) +
1352                                       ":" + cal.get(Calendar.SECOND) +
1353                                       "." + cal.get(Calendar.MILLISECOND));
1354 
1355                                 cal.clear();
1356                                 cal.set(fields[0], fields[1], fields[2],
1357                                         fields[3], fields[4], fields[5]);
1358                                 cal.set(Calendar.MILLISECOND, fields[6]);
1359                                 errln(cal.get(Calendar.YEAR) +
1360                                       "/" + (cal.get(Calendar.MONTH) + 1) +
1361                                       "/" + cal.get(Calendar.DATE) +
1362                                       " " + cal.get(Calendar.HOUR_OF_DAY) +
1363                                       ":" + cal.get(Calendar.MINUTE) +
1364                                       ":" + cal.get(Calendar.SECOND) +
1365                                       "." + cal.get(Calendar.MILLISECOND));
1366 
1367                                 long prev = cal.getTime().getTime();
1368                                 for (int i = 0; i < 2*limit; i++) {
1369                                     if (op == 0) {
1370                                         cal.add(field, i < limit ? 1 : -1);
1371                                     } else {
1372                                         cal.roll(field, i < limit ? 1 : -1);
1373                                     }
1374                                     long t = cal.getTime().getTime();
1375                                     long delta = t - prev;
1376                                     prev = t;
1377                                     errln((op == 0 ? "add(" : "roll(") +
1378                                           fieldNames[field] + ", " +
1379                                           (i < limit ? "+" : "-") + "1) => " +
1380                                           cal.get(Calendar.YEAR) +
1381                                           "/" + (cal.get(Calendar.MONTH) + 1) +
1382                                           "/" + cal.get(Calendar.DATE) +
1383                                           " " + cal.get(Calendar.HOUR_OF_DAY) +
1384                                           ":" + cal.get(Calendar.MINUTE) +
1385                                           ":" + cal.get(Calendar.SECOND) +
1386                                           "." + cal.get(Calendar.MILLISECOND) +
1387                                           " d=" + delta);
1388                                 }
1389                             }
1390                         }
1391                     }
1392                 }
1393             }
1394         }
1395         finally {
1396             Locale.setDefault(savedLocale);
1397         }
1398     }
1399 
1400     public void Test4174361() {
1401         GregorianCalendar calendar = new GregorianCalendar(1996, 1, 29);
1402 
1403         calendar.add(Calendar.MONTH, 10);
1404         Date date1 = calendar.getTime();
1405         int d1 = calendar.get(Calendar.DAY_OF_MONTH);
1406 
1407         calendar = new GregorianCalendar(1996, 1, 29);
1408         calendar.add(Calendar.MONTH, 11);
1409         Date date2 = calendar.getTime();
1410         int d2 = calendar.get(Calendar.DAY_OF_MONTH);
1411 
1412         if (d1 != d2) {
1413             errln("adding months to Feb 29 broken");
1414         }
1415     }
1416 
1417     /**
1418      * Calendar does not update field values when setTimeZone is called.
1419      */
1420     public void Test4177484() {
1421         TimeZone PST = TimeZone.getTimeZone("PST");
1422         TimeZone EST = TimeZone.getTimeZone("EST");
1423 
1424         Calendar cal = Calendar.getInstance(PST, Locale.US);
1425         cal.clear();
1426         cal.set(1999, 3, 21, 15, 5, 0); // Arbitrary
1427         int h1 = cal.get(Calendar.HOUR_OF_DAY);
1428         cal.setTimeZone(EST);
1429         int h2 = cal.get(Calendar.HOUR_OF_DAY);
1430         if (h1 == h2) {
1431             errln("FAIL: Fields not updated after setTimeZone");
1432         }
1433 
1434         // getTime() must NOT change when time zone is changed.
1435         // getTime() returns zone-independent time in ms.
1436         cal.clear();
1437         cal.setTimeZone(PST);
1438         cal.set(Calendar.HOUR_OF_DAY, 10);
1439         Date pst10 = cal.getTime();
1440         cal.setTimeZone(EST);
1441         Date est10 = cal.getTime();
1442         if (!pst10.equals(est10)) {
1443             errln("FAIL: setTimeZone changed time");
1444         }
1445     }
1446 
1447     /**
1448      * Week of year is wrong at the start and end of the year.
1449      */
1450     public void Test4197699() {
1451         GregorianCalendar cal = new GregorianCalendar();
1452         cal.setFirstDayOfWeek(Calendar.MONDAY);
1453         cal.setMinimalDaysInFirstWeek(4);
1454         DateFormat fmt = new SimpleDateFormat("E dd MMM yyyy  'DOY='D 'WOY='w");
1455         fmt.setCalendar(cal);
1456 
1457         int[] DATA = {
1458             2000,  Calendar.JANUARY,   1,   52,
1459             2001,  Calendar.DECEMBER,  31,  1,
1460         };
1461 
1462         for (int i=0; i<DATA.length; ) {
1463             cal.set(DATA[i++], DATA[i++], DATA[i++]);
1464             int expWOY = DATA[i++];
1465             int actWOY = cal.get(Calendar.WEEK_OF_YEAR);
1466             if (expWOY == actWOY) {
1467                 logln("Ok: " + fmt.format(cal.getTime()));
1468             } else {
1469                 errln("FAIL: " + fmt.format(cal.getTime())
1470                       + ", expected WOY=" + expWOY);
1471                 cal.add(Calendar.DATE, -8);
1472                 for (int j=0; j<14; ++j) {
1473                     cal.add(Calendar.DATE, 1);
1474                     logln(fmt.format(cal.getTime()));
1475                 }
1476             }
1477         }
1478     }
1479 
1480     /**
1481      * Calendar DAY_OF_WEEK_IN_MONTH fields->time broken.  The problem
1482      * is in the field disambiguation code in GregorianCalendar.  This
1483      * code is supposed to choose the most recent set of fields
1484      * among the following:
1485      *
1486      *   MONTH + DAY_OF_MONTH
1487      *   MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
1488      *   MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
1489      *   DAY_OF_YEAR
1490      *   WEEK_OF_YEAR + DAY_OF_WEEK
1491      */
1492     public void Test4209071() {
1493         Calendar cal = Calendar.getInstance(Locale.US);
1494 
1495         // General field setting test
1496         int Y = 1995 - 1900;
1497 
1498         Object[] FIELD_DATA = {
1499             // Add new test cases as needed.
1500 
1501             // 0
1502             new int[] {}, new Date(Y, Calendar.JANUARY, 1),
1503             // 1
1504             new int[] { Calendar.MONTH, Calendar.MARCH },
1505             new Date(Y, Calendar.MARCH, 1),
1506             // 2
1507             new int[] { Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY },
1508             new Date(Y, Calendar.JANUARY, 4),
1509             // 3
1510             new int[] { Calendar.DAY_OF_WEEK, Calendar.THURSDAY,
1511                         Calendar.DAY_OF_MONTH, 18, },
1512             new Date(Y, Calendar.JANUARY, 18),
1513             // 4
1514             new int[] { Calendar.DAY_OF_MONTH, 18,
1515                         Calendar.DAY_OF_WEEK, Calendar.THURSDAY, },
1516             new Date(Y, Calendar.JANUARY, 18),
1517             // 5  (WOM -1 is in previous month)
1518             new int[] { Calendar.DAY_OF_MONTH, 18,
1519                         Calendar.WEEK_OF_MONTH, -1,
1520                         Calendar.DAY_OF_WEEK, Calendar.THURSDAY, },
1521             new Date(Y-1, Calendar.DECEMBER, 22),
1522             // 6
1523             new int[] { Calendar.DAY_OF_MONTH, 18,
1524                         Calendar.WEEK_OF_MONTH, 4,
1525                         Calendar.DAY_OF_WEEK, Calendar.THURSDAY, },
1526             new Date(Y, Calendar.JANUARY, 26),
1527             // 7  (DIM -1 is in same month)
1528             new int[] { Calendar.DAY_OF_MONTH, 18,
1529                         Calendar.DAY_OF_WEEK_IN_MONTH, -1,
1530                         Calendar.DAY_OF_WEEK, Calendar.THURSDAY, },
1531             new Date(Y, Calendar.JANUARY, 26),
1532             // 8
1533             new int[] { Calendar.WEEK_OF_YEAR, 9,
1534                         Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY, },
1535             new Date(Y, Calendar.MARCH, 1),
1536             // 9
1537             new int[] { Calendar.MONTH, Calendar.OCTOBER,
1538                         Calendar.DAY_OF_WEEK_IN_MONTH, 1,
1539                         Calendar.DAY_OF_WEEK, Calendar.FRIDAY, },
1540             new Date(Y, Calendar.OCTOBER, 6),
1541             // 10
1542             new int[] { Calendar.MONTH, Calendar.OCTOBER,
1543                         Calendar.WEEK_OF_MONTH, 2,
1544                         Calendar.DAY_OF_WEEK, Calendar.FRIDAY, },
1545             new Date(Y, Calendar.OCTOBER, 13),
1546             // 11
1547             new int[] { Calendar.MONTH, Calendar.OCTOBER,
1548                         Calendar.DAY_OF_MONTH, 15,
1549                         Calendar.DAY_OF_YEAR, 222, },
1550             new Date(Y, Calendar.AUGUST, 10),
1551             // 12
1552             new int[] { Calendar.DAY_OF_WEEK, Calendar.THURSDAY,
1553                         Calendar.MONTH, Calendar.DECEMBER, },
1554             new Date(Y, Calendar.DECEMBER, 7),
1555         };
1556 
1557         for (int i=0; i<FIELD_DATA.length; i+=2) {
1558             int[] fields = (int[]) FIELD_DATA[i];
1559             Date exp = (Date) FIELD_DATA[i+1];
1560 
1561             cal.clear();
1562             cal.set(Calendar.YEAR, Y + 1900);
1563             for (int j=0; j<fields.length; j+=2) {
1564                 cal.set(fields[j], fields[j+1]);
1565             }
1566 
1567             Date act = cal.getTime();
1568             if (!act.equals(exp)) {
1569                 errln("FAIL: Test " + (i/2) + " got " + act +
1570                       ", want " + exp +
1571                       " (see test/java/util/Calendar/CalendarRegression.java");
1572             }
1573         }
1574 
1575         // Test specific failure reported in bug
1576         Object[] DATA = {
1577             new Integer(1), new Date(1997-1900, Calendar.JANUARY, 5),
1578             new Integer(4), new Date(1997-1900, Calendar.JANUARY, 26),
1579             new Integer(8), new Date(1997-1900, Calendar.FEBRUARY, 23),
1580             new Integer(-1), new Date(1997-1900, Calendar.JANUARY, 26),
1581             new Integer(-4), new Date(1997-1900, Calendar.JANUARY, 5),
1582             new Integer(-8), new Date(1996-1900, Calendar.DECEMBER, 8),
1583         };
1584         for (int i=0; i<DATA.length; i+=2) {
1585             cal.clear();
1586             cal.set(Calendar.DAY_OF_WEEK_IN_MONTH,
1587                     ((Number) DATA[i]).intValue());
1588             cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
1589             cal.set(Calendar.MONTH, Calendar.JANUARY);
1590             cal.set(Calendar.YEAR, 1997);
1591             Date actual = cal.getTime();
1592             if (!actual.equals(DATA[i+1])) {
1593                 errln("FAIL: Sunday " + DATA[i] +
1594                       " of Jan 1997 -> " + actual +
1595                       ", want " + DATA[i+1]);
1596             }
1597         }
1598     }
1599 
1600     public void Test4288792() throws Exception
1601     {
1602         TimeZone savedTZ = TimeZone.getDefault();
1603         TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
1604         GregorianCalendar cal = new GregorianCalendar();
1605         try {
1606             for (int i = 1900; i < 2100; i++) {
1607                 for (int j1 = 1; j1 <= 7; j1++) {
1608                     // Loop for MinimalDaysInFirstWeek: 1..7
1609                     for (int j = Calendar.SUNDAY; j <= Calendar.SATURDAY; j++) {
1610                         // Loop for FirstDayOfWeek: SUNDAY..SATURDAY
1611                         cal.clear();
1612                         cal.setMinimalDaysInFirstWeek(j1);
1613                         cal.setFirstDayOfWeek(j);
1614                         cal.set(Calendar.YEAR, i);
1615                         int maxWeek = cal.getActualMaximum(Calendar.WEEK_OF_YEAR);
1616                         cal.set(Calendar.WEEK_OF_YEAR, maxWeek);
1617                         cal.set(Calendar.DAY_OF_WEEK, j);
1618 
1619                         for (int k = 1; k < 7; k++) {
1620                             cal.add(Calendar.DATE, 1);
1621                             int WOY = cal.get(Calendar.WEEK_OF_YEAR);
1622                             if (WOY != maxWeek) {
1623                                 errln(cal.getTime() + ",got=" + WOY
1624                                       + ",expected=" + maxWeek
1625                                       + ",min=" + j1 + ",first=" + j);
1626                             }
1627                         }
1628 
1629                         cal.add(Calendar.DATE, 1);
1630                         int WOY = cal.get(Calendar.WEEK_OF_YEAR);
1631                         if (WOY != 1) {
1632                             errln(cal.getTime() + ",got=" + WOY
1633                                   + ",expected=1,min=" + j1 + ",first" + j);
1634                         }
1635                     }
1636                 }
1637             }
1638         }
1639         finally {
1640             TimeZone.setDefault(savedTZ);
1641         }
1642     }
1643 
1644     public void Test4328747() throws Exception {
1645         Calendar c = (Calendar)Calendar.getInstance(Locale.US);
1646         c.clear();
1647         c.set(1966,0,1); // 1 jan 1966
1648 
1649         // serialize
1650         ByteArrayOutputStream out = new ByteArrayOutputStream();
1651         ObjectOutputStream s = new ObjectOutputStream(out);
1652         s.writeObject(c);
1653         s.flush();
1654 
1655         // deserialize
1656         ObjectInputStream t = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray()));
1657         Calendar result = (Calendar)t.readObject();
1658 
1659         // let recalculate fields with the same UTC time
1660         result.setTime(result.getTime());
1661         // Bug gives 1965 11 19
1662         if ((result.get(c.YEAR) != 1966) || (result.get(c.MONTH) != 0)
1663             || (result.get(c.DATE) != 1)) {
1664             errln("deserialized Calendar returned wrong date field(s): "
1665                   + result.get(c.YEAR) + "/" + result.get(c.MONTH) + "/" + result.get(c.DATE)
1666                   + ", expected 1966/0/1");
1667         }
1668     }
1669 
1670     /**
1671      * Test whether Calendar can be serialized/deserialized correctly
1672      * even if invalid/customized TimeZone is used.
1673      */
1674     public void Test4413980() {
1675         TimeZone savedTimeZone = TimeZone.getDefault();
1676         try {
1677             boolean pass = true;
1678             String[] IDs = new String[] {"Undefined", "PST", "US/Pacific",
1679                                          "GMT+3:00", "GMT-01:30"};
1680             for (int i = 0; i < IDs.length; i++) {
1681                 TimeZone tz = TimeZone.getTimeZone(IDs[i]);
1682                 TimeZone.setDefault(tz);
1683 
1684                 Calendar c = (Calendar)Calendar.getInstance();
1685 
1686                 // serialize
1687                 ByteArrayOutputStream out = new ByteArrayOutputStream();
1688                 ObjectOutputStream s = new ObjectOutputStream(out);
1689                 s.writeObject(c);
1690                 s.flush();
1691 
1692                 // deserialize
1693                 ObjectInputStream t = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray()));
1694 
1695                 if (!c.equals(t.readObject())) {
1696                     pass = false;
1697                     logln("Calendar instance which uses TimeZone <" +
1698                           IDs[i] + "> is incorrectly serialized/deserialized.");
1699                 } else {
1700                     logln("Calendar instance which uses TimeZone <" +
1701                           IDs[i] + "> is correctly serialized/deserialized.");
1702                 }
1703             }
1704             if (!pass) {
1705                 errln("Fail: Calendar serialization/equality bug");
1706             }
1707         }
1708         catch (IOException e) {
1709             errln("Fail: " + e);
1710             e.printStackTrace();
1711         }
1712         catch (ClassNotFoundException e) {
1713             errln("Fail: " + e);
1714             e.printStackTrace();
1715         }
1716         finally {
1717             TimeZone.setDefault(savedTimeZone);
1718         }
1719     }
1720 
1721     /**
1722      * 4546637: Incorrect WEEK_OF_MONTH after changing First Day Of Week
1723      */
1724     public void Test4546637() {
1725         GregorianCalendar day = new GregorianCalendar (2001, Calendar.NOVEMBER, 04);
1726         day.setMinimalDaysInFirstWeek(1);
1727         int wom = day.get(Calendar.WEEK_OF_MONTH);
1728 
1729         day.setFirstDayOfWeek(Calendar.MONDAY);
1730         if (day.get(Calendar.WEEK_OF_MONTH) != 1) {
1731             errln("Fail: 2001/11/4 must be the first week of the month.");
1732         }
1733     }
1734 
1735     /**
1736      * 4623997: GregorianCalendar returns bad WEEK_OF_YEAR
1737      */
1738     public void Test4623997() {
1739         GregorianCalendar cal = new GregorianCalendar(2000, GregorianCalendar.JANUARY, 1);
1740 
1741         int dow = cal.get(GregorianCalendar.DAY_OF_WEEK);
1742 
1743         cal.setFirstDayOfWeek(GregorianCalendar.MONDAY);
1744         cal.setMinimalDaysInFirstWeek(4);
1745 
1746         if (cal.get(GregorianCalendar.WEEK_OF_YEAR) != 52) {
1747             errln("Fail: 2000/1/1 must be the 52nd week of the year.");
1748         }
1749     }
1750 
1751     /**
1752      * 4685354: Handling of Calendar fields setting state is broken
1753      *
1754      * <p>Need to use SimpleDateFormat to test because a call to
1755      * get(int) changes internal states of a Calendar.
1756      */
1757     public void Test4685354() {
1758         if (Locale.getDefault().equals(new Locale("hi", "IN"))) {
1759             return;
1760         }
1761 
1762         Calendar calendar = Calendar.getInstance(Locale.US);
1763         DateFormat df = new SimpleDateFormat("yyyy/MM/dd", Locale.US);
1764         String expected = "1999/12/31";
1765         Date t;
1766         String s;
1767 
1768         try {
1769             calendar.setTime(df.parse(expected));
1770         } catch (Exception e) {
1771             throw new RuntimeException("Unexpected parse exception", e);
1772         }
1773 
1774         t = calendar.getTime();
1775         calendar.set(Calendar.DAY_OF_MONTH, 33);
1776         t = calendar.getTime();
1777         calendar.set(Calendar.DAY_OF_MONTH, 0);
1778         s = df.format(calendar.getTime());
1779         if (!expected.equals(s)) {
1780             errln("DAY_OF_MONTH w/o ZONE_OFFSET: expected: " + expected + ", got: " + s);
1781         }
1782 
1783         // The same thing must work with ZONE_OFFSET set
1784         try {
1785             calendar.setTime(df.parse(expected));
1786         } catch (Exception e) {
1787             throw new RuntimeException("Unexpected parse exception", e);
1788         }
1789         t = calendar.getTime();
1790         calendar.set(calendar.ZONE_OFFSET, calendar.get(calendar.ZONE_OFFSET));
1791         calendar.set(Calendar.DAY_OF_MONTH, 33);
1792         t = calendar.getTime();
1793         calendar.set(Calendar.DAY_OF_MONTH, 0);
1794         s = df.format(calendar.getTime());
1795         if (!expected.equals(s)) {
1796             errln("DAY_OF_MONTH: expected: " + expected + ", got: " + s);
1797         }
1798 
1799         expected = "1999/12/24"; // 0th week of 2000
1800         calendar.clear();
1801         Date initialDate = null;
1802         try {
1803             initialDate = df.parse(expected);
1804             calendar.setTime(initialDate);
1805         } catch (Exception e) {
1806             throw new RuntimeException("Unexpected parse exception", e);
1807         }
1808         t = calendar.getTime();
1809         calendar.set(calendar.ZONE_OFFSET, calendar.get(calendar.ZONE_OFFSET));
1810         // jump to the next year
1811         calendar.set(Calendar.WEEK_OF_YEAR, 100);
1812         t = calendar.getTime();
1813         calendar.set(Calendar.WEEK_OF_YEAR, 0);
1814         s = df.format(calendar.getTime());
1815         if (!expected.equals(s)) {
1816             errln("WEEK_OF_YEAR: expected: " + expected + ", got: " + s);
1817         }
1818         // change the state back
1819         calendar.clear();
1820         calendar.setTime(initialDate);
1821         calendar.set(calendar.ZONE_OFFSET, calendar.get(calendar.ZONE_OFFSET));
1822         // jump to next month
1823         calendar.set(Calendar.WEEK_OF_MONTH, 7);
1824         t = calendar.getTime();
1825         calendar.set(Calendar.WEEK_OF_MONTH, 0);
1826         s = df.format(calendar.getTime());
1827         if (!expected.equals(s)) {
1828             errln("WEEK_OF_MONTH: expected: " + expected + ", got: " + s);
1829         }
1830 
1831         // Make sure the time fields work correctly.
1832         calendar.clear();
1833         df = new SimpleDateFormat("HH:mm:ss");
1834         TimeZone tz = TimeZone.getTimeZone("GMT");
1835         df.setTimeZone(tz);
1836         calendar.setTimeZone(tz);
1837         expected = "22:59:59";
1838         try {
1839             calendar.setTime(df.parse(expected));
1840         } catch (Exception e) {
1841             throw new RuntimeException("Unexpected parse exception", e);
1842         }
1843         t = calendar.getTime();
1844         // time should be 22:59:59.
1845         calendar.set(Calendar.MINUTE, 61);
1846         // time should be 23:01:59.
1847         t = calendar.getTime();
1848         calendar.set(Calendar.MINUTE, -1);
1849         // time should be back to 22:59:59.
1850         s = df.format(calendar.getTime());
1851         if (!expected.equals(s)) {
1852             errln("MINUTE: expected: " + expected + ", got: " + s);
1853         }
1854     }
1855 
1856     /**
1857      * 4655637: Calendar.set() for DAY_OF_WEEK does not return the right value
1858      *
1859      * <p>Need to use SimpleDateFormat to test because a call to
1860      * get(int) changes internal states of a Calendar.
1861      */
1862     public void Test4655637() {
1863         // Skip this test case if it's Thai locale
1864         if (Locale.getDefault().equals(new Locale("th", "TH"))) {
1865             return;
1866         }
1867 
1868         Calendar cal = Calendar.getInstance();
1869         cal.setTime(new Date(1029814211523L));
1870         cal.set(Calendar.YEAR, 2001);
1871         Date t = cal.getTime();
1872         cal.set(Calendar.MONTH, Calendar.JANUARY);
1873         t = cal.getTime();
1874 
1875         cal.set(Calendar.DAY_OF_MONTH, 8);
1876         t = cal.getTime();
1877 
1878         cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
1879         DateFormat df = new SimpleDateFormat("yyyy/MM/dd", Locale.US);
1880         String expected = "2001/01/08";
1881         String s = df.format(cal.getTime());
1882         if (!expected.equals(s)) {
1883             errln("expected: " + expected + ", got: " + s);
1884         }
1885     }
1886 
1887     /**
1888      * 4683492: Invalid value for MONTH in GregorianCalendar causes exception in getTime().
1889      *
1890      * <p>Need to use SimpleDateFormat to test because a call to
1891      * get(int) changes internal states of a Calendar.
1892      *
1893      * <p>This test case throws ArrayIndexOutOfBoundsException without the fix.
1894      */
1895     public void Test4683492() {
1896         Calendar cal = new GregorianCalendar(2002, 3, 29, 10, 0, 0);
1897         cal.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);
1898         cal.set(Calendar.DAY_OF_WEEK_IN_MONTH, -1);
1899         cal.set(Calendar.MONTH, 12);
1900         DateFormat df = new SimpleDateFormat("yyyy/MM/dd", Locale.US);
1901         String expected = "2003/01/31";
1902         String s = df.format(cal.getTime());
1903         if (!expected.equals(s)) {
1904             errln("expected: " + expected + ", got: " + s);
1905         }
1906     }
1907 
1908     /**
1909      * 4080631: Calendar.hashCode is amazingly bad
1910      */
1911     public void Test4080631() {
1912         Calendar cal = Calendar.getInstance();
1913         int h1 = cal.hashCode();
1914         cal.add(cal.SECOND, +1);
1915         int h2 = cal.hashCode();
1916         Calendar cal2 = (Calendar) cal.clone();
1917         cal.add(cal.MILLISECOND, +1);
1918         int h3 = cal.hashCode();
1919         logln("hash code: h1="+h1+", h2="+h2+", h3="+h3);
1920         if (h1 == h2 || h1 == h3 || h2 == h3) {
1921             errln("hash code is poor: hashCode="+h1);
1922         }
1923         h2 = cal2.hashCode();
1924         cal.add(cal.MILLISECOND, -1);
1925         int h4 = cal.hashCode();
1926         logln("hash code: h2="+h2+", h4="+h4);
1927         if (cal.equals(cal2) && h2 != h4) {
1928             errln("broken hash code: h2="+h2+", h4="+h4);
1929         }
1930         int x = cal.getFirstDayOfWeek() + 3;
1931         if (x > cal.SATURDAY) {
1932             x -= 7;
1933         }
1934         cal.setFirstDayOfWeek(x);
1935         int h5 = cal.hashCode();
1936         logln("hash code: h4="+h4+", h5="+h5);
1937         if (h4 == h5) {
1938             errln("has code is poor with first day of week param: hashCode="+h4);
1939         }
1940     }
1941 
1942     /**
1943      * 4125161: RFE: GregorianCalendar needs more era names (BCE and CE)
1944      */
1945     /*
1946     public void Test4125161() throws Exception {
1947         Class gc = GregorianCalendar.class;
1948         Field f;
1949         int mod;
1950         f = gc.getDeclaredField("BCE");
1951         mod = f.getModifiers();
1952         if (!Modifier.isStatic(mod) || !Modifier.isFinal(mod)) {
1953             errln("BCE: wrong modifiers: " + mod);
1954         }
1955         f = gc.getDeclaredField("CE");
1956         mod = f.getModifiers();
1957         if (!Modifier.isStatic(mod) || !Modifier.isFinal(mod)) {
1958             errln("CE: wrong modifiers: " + mod);
1959         }
1960         if (GregorianCalendar.BCE != GregorianCalendar.BC
1961             || GregorianCalendar.CE != GregorianCalendar.AD) {
1962             errln("Wrong BCE and/or CE values");
1963         }
1964     }
1965     */
1966 
1967     /**
1968      * 4167995: GregorianCalendar.setGregorianChange() not to spec
1969      */
1970     public void Test4167995() {
1971         Koyomi gc = new Koyomi(TimeZone.getTimeZone("GMT"));
1972         logln("Hybrid: min date");
1973         gc.setTime(new Date(Long.MIN_VALUE));
1974         if (!gc.checkDate(292269055, gc.DECEMBER, 2, gc.SUNDAY)
1975             || !gc.checkFieldValue(gc.ERA, gc.BC)) {
1976             errln(gc.getMessage());
1977         }
1978         logln("Hybrid: max date");
1979         gc.setTime(new Date(Long.MAX_VALUE));
1980         if (!gc.checkDate(292278994, gc.AUGUST, 17, gc.SUNDAY)
1981             || !gc.checkFieldValue(gc.ERA, gc.AD)) {
1982             errln(gc.getMessage());
1983         }
1984 
1985         gc.setGregorianChange(new Date(Long.MIN_VALUE));
1986         logln("Gregorian: min date");
1987         gc.setTime(new Date(Long.MIN_VALUE));
1988         if (!gc.checkDate(292275056, gc.MAY, 16, gc.SUNDAY)
1989             || !gc.checkFieldValue(gc.ERA, gc.BC)) {
1990             errln(gc.getMessage());
1991         }
1992         logln("Gregorian: max date");
1993         gc.setTime(new Date(Long.MAX_VALUE));
1994         if (!gc.checkDate(292278994, gc.AUGUST, 17, gc.SUNDAY)
1995             || !gc.checkFieldValue(gc.ERA, gc.AD)) {
1996             errln(gc.getMessage());
1997         }
1998 
1999         gc.setGregorianChange(new Date(Long.MAX_VALUE));
2000         logln("Julian: min date");
2001         gc.setTime(new Date(Long.MIN_VALUE));
2002         if (!gc.checkDate(292269055, gc.DECEMBER, 2, gc.SUNDAY)
2003             || !gc.checkFieldValue(gc.ERA, gc.BC)) {
2004             errln(gc.getMessage());
2005         }
2006         logln("Julian: max date");
2007         gc.setTime(new Date(Long.MAX_VALUE));
2008         if (!gc.checkDate(292272993, gc.JANUARY, 4, gc.SUNDAY)
2009             || !gc.checkFieldValue(gc.ERA, gc.AD)) {
2010             errln(gc.getMessage());
2011         }
2012     }
2013 
2014     /**
2015      * 4340146: Calendar.equals modifies state
2016      */
2017     public void Test4340146() {
2018         Koyomi cal = new Koyomi();
2019         cal.clear();
2020         cal.set(2003, cal.OCTOBER, 32);
2021         cal.equals(new Koyomi());
2022         if (!cal.checkInternalDate(2003, cal.OCTOBER, 32)) {
2023             errln(cal.getMessage());
2024         }
2025         new Koyomi().equals(cal);
2026         if (!cal.checkInternalDate(2003, cal.OCTOBER, 32)) {
2027             errln(cal.getMessage());
2028         }
2029     }
2030 
2031     /**
2032      * 4639407: GregorianCalendar doesn't work in non-lenient due to timezone bounds checking
2033      */
2034     public void Test4639407() {
2035         // The following operations in non-lenient mode shouldn't
2036         // throw IllegalArgumentException.
2037         Koyomi cal = new Koyomi(TimeZone.getTimeZone("Pacific/Kiritimati"));
2038         cal.setLenient(false);
2039         cal.set(2003, cal.OCTOBER, 10);
2040         cal.getTime();
2041         cal.setTimeZone(TimeZone.getTimeZone("Pacific/Tongatapu"));
2042         cal.set(2003, cal.OCTOBER, 10);
2043         cal.getTime();
2044     }
2045 
2046     /**
2047      * 4652815: rolling week-of-year back hundreds of weeks changes year
2048      */
2049     public void Test4652815() {
2050         Koyomi cal = new Koyomi(Locale.US);
2051         testRoll(cal, 2003, cal.SEPTEMBER, 29);
2052         testRoll(cal, 2003, cal.DECEMBER, 24);
2053         testRoll(cal, 1582, cal.DECEMBER, 19);
2054         testRoll(cal, 1582, cal.DECEMBER, 20);
2055     }
2056 
2057     private void testRoll(Koyomi cal, int year, int month, int dayOfMonth) {
2058         cal.clear();
2059         cal.set(year, month, dayOfMonth);
2060         cal.getTime(); // normalize fields
2061         logln("Roll backwards from " + cal.toDateString());
2062         for (int i = 0; i < 1000; i++) {
2063             cal.roll(cal.WEEK_OF_YEAR, -i);
2064             if (!cal.checkFieldValue(cal.YEAR, year)) {
2065                 errln(cal.getMessage());
2066             }
2067         }
2068         logln("Roll forewards from " + cal.toDateString());
2069         for (int i = 0; i < 1000; i++) {
2070             cal.roll(cal.WEEK_OF_YEAR, +i);
2071             if (!cal.checkFieldValue(cal.YEAR, year)) {
2072                 errln(cal.getMessage());
2073             }
2074         }
2075     }
2076 
2077     /**
2078      * 4652830: GregorianCalendar roll behaves unexpectedly for dates in BC era
2079      */
2080     public void Test4652830() {
2081         Koyomi cal = new Koyomi(Locale.US);
2082         cal.clear();
2083         logln("BCE 9-2-28 (leap year) roll DAY_OF_MONTH++ twice");
2084         cal.set(cal.ERA, cal.BC);
2085         cal.set(9, cal.FEBRUARY, 28);
2086         if (cal.getActualMaximum(cal.DAY_OF_YEAR) != 366) {
2087             errln("    wrong actual max of DAY_OF_YEAR: got "
2088                   + cal.getActualMaximum(cal.DAY_OF_YEAR) + " expected " + 366);
2089         }
2090         cal.roll(cal.DAY_OF_MONTH, +1);
2091         if (!cal.checkFieldValue(cal.ERA, cal.BC)
2092             || !cal.checkDate(9, cal.FEBRUARY, 29)) {
2093             errln(cal.getMessage());
2094         }
2095         cal.roll(cal.DAY_OF_MONTH, +1);
2096         if (!cal.checkFieldValue(cal.ERA, cal.BC)
2097             || !cal.checkDate(9, cal.FEBRUARY, 1)) {
2098             errln(cal.getMessage());
2099         }
2100     }
2101 
2102     /**
2103      * 4740554: GregorianCalendar.getActualMaximum is inconsistent with normalization
2104      */
2105     public void Test4740554() {
2106         logln("1999/(Feb+12)/1 should be normalized to 2000/Feb/1 for getActualMaximum");
2107         Koyomi cal = new Koyomi(Locale.US);
2108         cal.clear();
2109         cal.set(1999, cal.FEBRUARY + 12, 1);
2110         if (!cal.checkActualMaximum(cal.DAY_OF_YEAR, 366)) {
2111             errln(cal.getMessage());
2112         }
2113         if (!cal.checkActualMaximum(cal.DAY_OF_MONTH, 29)) {
2114             errln(cal.getMessage());
2115         }
2116     }
2117 
2118     /**
2119      * 4936355: GregorianCalendar causes overflow/underflow with time of day calculation
2120      */
2121     public void Test4936355() {
2122         Koyomi cal = new Koyomi(TimeZone.getTimeZone("GMT"));
2123         cal.clear();
2124         cal.set(1970, cal.JANUARY, 1);
2125         checkTimeCalculation(cal, cal.HOUR_OF_DAY, Integer.MAX_VALUE,
2126                              (long)Integer.MAX_VALUE * 60 * 60 * 1000);
2127 
2128         cal.clear();
2129         cal.set(1970, cal.JANUARY, 1);
2130         checkTimeCalculation(cal, cal.HOUR, Integer.MAX_VALUE,
2131                              (long)Integer.MAX_VALUE * 60 * 60 * 1000);
2132 
2133         cal.clear();
2134         cal.set(1970, cal.JANUARY, 1);
2135         checkTimeCalculation(cal, cal.MINUTE, Integer.MAX_VALUE,
2136                              (long)Integer.MAX_VALUE * 60 * 1000);
2137 
2138         cal.clear();
2139         // Make sure to use Gregorian dates (before and after the
2140         // set() call) for testing
2141         cal.set(250000, cal.JANUARY, 1);
2142         checkTimeCalculation(cal, cal.HOUR_OF_DAY, Integer.MIN_VALUE,
2143                              (long)Integer.MIN_VALUE * 60 * 60 * 1000);
2144 
2145         cal.clear();
2146         cal.set(250000, cal.JANUARY, 1);
2147         checkTimeCalculation(cal, cal.HOUR, Integer.MIN_VALUE,
2148                              (long)Integer.MIN_VALUE * 60 * 60 * 1000);
2149 
2150         cal.clear();
2151         cal.set(250000, cal.JANUARY, 1);
2152         checkTimeCalculation(cal, cal.MINUTE, Integer.MIN_VALUE,
2153                              (long)Integer.MIN_VALUE * 60 * 1000);
2154     }
2155 
2156     private void checkTimeCalculation(Koyomi cal, int field, int value, long expectedDelta) {
2157         long time = cal.getTimeInMillis();
2158         cal.set(field, value);
2159         long time2 = cal.getTimeInMillis();
2160         if ((time + expectedDelta) != time2) {
2161             String s = value == Integer.MAX_VALUE ? "Integer.MAX_VALUE" : "Integer.MIN_VALUE";
2162             errln("set(" + Koyomi.getFieldName(field) + ", " + s + ") failed." + " got " + time2
2163                   + ", expected " + (time+expectedDelta));
2164         }
2165     }
2166 
2167     /**
2168      * 4722650: Calendar.equals can throw an exception in non-lenient
2169      * (piggy-back tests for compareTo() which is new in 1.5)
2170      */
2171     public void Test4722650() {
2172         Calendar cal1 = new GregorianCalendar();
2173         cal1.clear();
2174         Calendar cal2 = new GregorianCalendar();
2175         cal2.clear();
2176         cal2.setLenient(false);
2177 
2178         cal1.set(2003, Calendar.OCTOBER, 31);
2179         cal2.set(2003, Calendar.OCTOBER, 31);
2180         try {
2181             if (cal1.equals(cal2)) {
2182                 errln("lenient and non-lenient shouldn't be equal. (2003/10/31)");
2183             }
2184             if (cal1.compareTo(cal2) != 0) {
2185                 errln("cal1 and cal2 should represent the same time. (2003/10/31)");
2186             }
2187         } catch (IllegalArgumentException e) {
2188             errln("equals threw IllegalArugumentException with non-lenient");
2189         }
2190 
2191         cal1.set(2003, Calendar.OCTOBER, 32);
2192         cal2.set(2003, Calendar.OCTOBER, 32);
2193         try {
2194             if (cal1.equals(cal2)) {
2195                 errln("lenient and non-lenient shouldn't be equal. (2003/10/32)");
2196             }
2197             if (cal1.compareTo(cal2) != 0) {
2198                 errln("cal1 and cal2 should represent the same time. (2003/10/32)");
2199             }
2200         } catch (IllegalArgumentException e) {
2201             errln("equals threw IllegalArugumentException with non-lenient");
2202         }
2203 
2204         cal1 = Calendar.getInstance(new Locale("th", "TH"));
2205         cal1.setTimeInMillis(0L);
2206         cal2 = Calendar.getInstance(Locale.US);
2207         cal2.setTimeInMillis(0L);
2208         if (cal1.equals(cal2)) {
2209             errln("Buddhist.equals(Gregorian) shouldn't be true. (millis=0)");
2210         }
2211         if (cal1.compareTo(cal2) != 0) {
2212             errln("cal1 (Buddhist) and cal2 (Gregorian) should represent the same time. (millis=0)");
2213         }
2214     }
2215 
2216     /**
2217      * 4738710: API: Calendar comparison methods should be improved
2218      */
2219     public void Test4738710() {
2220         Calendar cal0 = new GregorianCalendar(2003, Calendar.SEPTEMBER, 30);
2221         Comparable<Calendar> cal1 = new GregorianCalendar(2003, Calendar.OCTOBER, 1);
2222         Calendar cal2 = new GregorianCalendar(2003, Calendar.OCTOBER, 2);
2223         if (!(cal1.compareTo(cal0) > 0)) {
2224             errln("!(cal1 > cal0)");
2225         }
2226         if (!(cal1.compareTo(cal2) < 0)) {
2227             errln("!(cal1 < cal2)");
2228         }
2229         if (cal1.compareTo(new GregorianCalendar(2003, Calendar.OCTOBER, 1)) != 0) {
2230             errln("cal1 != new GregorianCalendar(2003, Calendar.OCTOBER, 1)");
2231         }
2232 
2233         if (cal0.after(cal2)) {
2234             errln("cal0 shouldn't be after cal2");
2235         }
2236         if (cal2.before(cal0)) {
2237             errln("cal2 shouldn't be before cal0");
2238         }
2239 
2240         if (cal0.after(new Integer(0))) {
2241             errln("cal0.after() returned true with an Integer.");
2242         }
2243         if (cal0.before(new Integer(0))) {
2244             errln("cal0.before() returned true with an Integer.");
2245         }
2246         if (cal0.after(null)) {
2247             errln("cal0.after() returned true with null.");
2248         }
2249         if (cal0.before(null)) {
2250             errln("cal0.before() returned true with null.");
2251         }
2252     }
2253 
2254     /**
2255      * 4633646: Setting WEEK_OF_MONTH to 1 results in incorrect date
2256      */
2257     public void Test4633646() {
2258         Koyomi cal = new Koyomi(Locale.US);
2259         cal.setTime(new Date(2002-1900, 1-1, 28));
2260         sub4633646(cal);
2261 
2262         cal.setLenient(false);
2263         cal.setTime(new Date(2002-1900, 1-1, 28));
2264         sub4633646(cal);
2265 
2266         cal = new Koyomi(Locale.US);
2267         cal.clear();
2268         cal.set(2002, cal.JANUARY, 28);
2269         sub4633646(cal);
2270 
2271         cal.clear();
2272         cal.setLenient(false);
2273         cal.set(2002, cal.JANUARY, 28);
2274         sub4633646(cal);
2275     }
2276 
2277     void sub4633646(Koyomi cal) {
2278         cal.getTime();
2279         cal.set(cal.WEEK_OF_MONTH, 1);
2280         if (cal.isLenient()) {
2281             if (!cal.checkDate(2001, cal.DECEMBER, 31)) {
2282                 errln(cal.getMessage());
2283             }
2284             if (!cal.checkFieldValue(cal.WEEK_OF_MONTH, 6)) {
2285                 errln(cal.getMessage());
2286             }
2287         } else {
2288             try {
2289                 Date d = cal.getTime();
2290                 errln("didn't throw IllegalArgumentException in non-lenient");
2291             } catch (IllegalArgumentException e) {
2292             }
2293         }
2294     }
2295 
2296     /**
2297      * 4846659: Calendar: Both set() and roll() don't work for AM_PM time field
2298      * (Partially fixed only roll as of 1.5)
2299      */
2300     public void Test4846659() {
2301         Koyomi cal = new Koyomi();
2302         cal.clear();
2303         cal.set(2003, cal.OCTOBER, 31, 10, 30, 30);
2304         cal.getTime();
2305         // Test roll()
2306         cal.roll(cal.AM_PM, +1); // should turn to PM
2307         if (!cal.checkFieldValue(cal.HOUR_OF_DAY, 10+12)) {
2308             errln("roll: AM_PM didn't change to PM");
2309         }
2310 
2311         cal.clear();
2312         cal.set(2003, cal.OCTOBER, 31, 10, 30, 30);
2313         cal.getTime();
2314         // Test set()
2315         cal.set(cal.AM_PM, cal.PM); // should turn to PM
2316         if (!cal.checkFieldValue(cal.HOUR_OF_DAY, 10+12)) {
2317             errln("set: AM_PM didn't change to PM");
2318         }
2319 
2320         cal.clear();
2321         cal.set(2003, cal.OCTOBER, 31, 10, 30, 30);
2322         cal.getTime();
2323         cal.set(cal.AM_PM, cal.PM);
2324         cal.set(cal.HOUR, 9);
2325         if (!cal.checkFieldValue(cal.HOUR_OF_DAY, 9+12)) {
2326             errln("set: both AM_PM and HOUT didn't change to PM");
2327         }
2328     }
2329 
2330     /**
2331      * 4822110: GregorianCalendar.get() returns an incorrect date after setFirstDayOfWeek()
2332      */
2333     public void Test4822110() {
2334         Koyomi cal = new Koyomi(Locale.US);
2335         //    June 2003
2336         //  S  M Tu  W Th  F  S
2337         //  1  2  3  4  5  6  7
2338         //  8  9 10 11 12 13 14
2339         // 15 16 17 18 19 20 21
2340         // 22 23 24 25 26 27 28
2341         // 29 30
2342         cal.clear();
2343         // 6/1 to 6/7 should be the 1st week of June.
2344         cal.set(2003, cal.JUNE, 2);
2345         cal.getTime();                  // Let cal calculate time.
2346         cal.setFirstDayOfWeek(cal.MONDAY);
2347         // Now 6/2 to 6/8 should be the 2nd week of June. Sunday of
2348         // that week is 6/8.
2349         logln("1: " +cal.get(cal.WEEK_OF_MONTH)+", "+cal.get(cal.DAY_OF_MONTH));
2350         cal.set(cal.DAY_OF_WEEK, cal.SUNDAY);
2351         logln("1st Sunday of June 2003 with FirstDayOfWeek=MONDAY");
2352         if (!cal.checkDate(2003, cal.JUNE, 8)) {
2353             errln(cal.getMessage());
2354         }
2355     }
2356 
2357     /**
2358      * 4973919: Inconsistent GregorianCalendar hashCode before and after serialization
2359      */
2360     public void Test4966499() throws Exception {
2361         GregorianCalendar date1 = new GregorianCalendar(2004, Calendar.JANUARY, 7);
2362 
2363         // Serialize date1
2364         ByteArrayOutputStream baos = new ByteArrayOutputStream();
2365         ObjectOutputStream oos = new ObjectOutputStream(baos);
2366         oos.writeObject(date1);
2367 
2368         byte[] buffer = baos.toByteArray();
2369 
2370         // Deserialize it
2371         ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
2372         ObjectInputStream ois = new ObjectInputStream(bais);
2373         GregorianCalendar date2 = (GregorianCalendar)ois.readObject();
2374 
2375         if (!date1.equals(date2)) {
2376             errln("date1.equals(date2) != true");
2377         }
2378         if (date1.hashCode() != date2.hashCode()) {
2379             errln("inconsistent hashCode() value (before=0x"
2380                   +Integer.toHexString(date1.hashCode())+
2381                   ", after=0x"+Integer.toHexString(date2.hashCode())+")");
2382         }
2383     }
2384 
2385     /**
2386      * 4980088: GregorianCalendar.getActualMaximum doesn't throw exception
2387      */
2388     public void Test4980088() {
2389         GregorianCalendar cal = new GregorianCalendar();
2390         try {
2391             int x = cal.getMaximum(100);
2392             errln("getMaximum(100) didn't throw an exception.");
2393         } catch (IndexOutOfBoundsException e) {
2394             logln("getMaximum: " + e.getClass().getName() + ": " + e.getMessage());
2395         }
2396 
2397         try {
2398             int x = cal.getLeastMaximum(100);
2399             errln("getLeastMaximum(100) didn't throw an exception.");
2400         } catch (IndexOutOfBoundsException e) {
2401             logln("getLeastMaximum: " + e.getClass().getName() + ": " + e.getMessage());
2402         }
2403 
2404         try {
2405             int x = cal.getActualMaximum(100);
2406             errln("getActualMaximum(100) didn't throw an exception.");
2407         } catch (IndexOutOfBoundsException e) {
2408             logln("getActualMaximum: " + e.getClass().getName() + ": " + e.getMessage());
2409         }
2410 
2411         try {
2412             int x = cal.getMinimum(100);
2413             errln("getMinimum(100) didn't throw an exception.");
2414         } catch (IndexOutOfBoundsException e) {
2415             logln("getMinimum: " + e.getClass().getName() + ": " + e.getMessage());
2416         }
2417 
2418         try {
2419             int x = cal.getGreatestMinimum(100);
2420             errln("getGreatestMinimum(100) didn't throw an exception.");
2421         } catch (IndexOutOfBoundsException e) {
2422             logln("getGreatestMinimum: " + e.getClass().getName() + ": " + e.getMessage());
2423         }
2424 
2425         try {
2426             int x = cal.getActualMinimum(100);
2427             errln("getActualMinimum(100) didn't throw an exception.");
2428         } catch (IndexOutOfBoundsException e) {
2429             logln("getActualMinimum: " + e.getClass().getName() + ": " + e.getMessage());
2430         }
2431     }
2432 
2433     /**
2434      * 4965624: GregorianCalendar.isLeapYear(1000) returns incorrect value
2435      */
2436     public void Test4965624() {
2437         // 5013094: This test case needs to use "GMT" to specify
2438         // Gregorian cutover dates.
2439         TimeZone savedZone = TimeZone.getDefault();
2440         TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
2441         try {
2442             Map<Date, Boolean> data = new HashMap<Date, Boolean>();
2443             data.put(getGregorianDate(999, Calendar.OCTOBER, 1), Boolean.FALSE);
2444             data.put(getGregorianDate(1000, Calendar.JANUARY, 1), Boolean.FALSE);
2445             data.put(getGregorianDate(1000, Calendar.FEBRUARY, 1), Boolean.FALSE);
2446             data.put(getGregorianDate(1000, Calendar.FEBRUARY, 28), Boolean.FALSE);
2447             data.put(getGregorianDate(1000, Calendar.MARCH, 1), Boolean.TRUE);
2448             data.put(getGregorianDate(1001, Calendar.JANUARY, 1), Boolean.TRUE);
2449             data.put(getGregorianDate(1001, Calendar.JANUARY, 6), Boolean.TRUE);
2450             data.put(getGregorianDate(1001, Calendar.MARCH, 1), Boolean.TRUE);
2451 
2452             Iterator<Date> itr = data.keySet().iterator();
2453             while (itr.hasNext()) {
2454                 Date d = itr.next();
2455                 boolean expected = data.get(d).booleanValue();
2456                 GregorianCalendar cal = new GregorianCalendar();
2457                 cal.setGregorianChange(d);
2458                 if (cal.isLeapYear(1000) != expected) {
2459                     errln("isLeapYear(1000) returned " + cal.isLeapYear(1000) +
2460                           " with cutover date (Julian) " + d);
2461                 }
2462             }
2463         }
2464         finally {
2465             TimeZone.setDefault(savedZone);
2466         }
2467     }
2468 
2469     // Note that we can't use Date to produce Gregorian calendar dates
2470     // before the default cutover date.
2471     static Date getGregorianDate(int year, int month, int dayOfMonth) {
2472         GregorianCalendar g = new GregorianCalendar();
2473         // Make g a pure Gregorian calendar
2474         g.setGregorianChange(new Date(Long.MIN_VALUE));
2475         g.clear();
2476         g.set(year, month, dayOfMonth);
2477         return g.getTime();
2478     }
2479 
2480     /**
2481      * 5006864: Define the minimum value of DAY_OF_WEEK_IN_MONTH as 1
2482      */
2483     public void Test5006864() {
2484         GregorianCalendar cal = new GregorianCalendar();
2485         int min = cal.getMinimum(cal.DAY_OF_WEEK_IN_MONTH);
2486         if (min != 1) {
2487             errln("GregorianCalendar.getMinimum(DAY_OF_WEEK_IN_MONTH) returned "
2488                   + min + ", expected 1.");
2489         }
2490         min = cal.getGreatestMinimum(cal.DAY_OF_WEEK_IN_MONTH);
2491         if (min != 1) {
2492             errln("GregorianCalendar.getGreatestMinimum(DAY_OF_WEEK_IN_MONTH) returned "
2493                   + min + ", expected 1.");
2494         }
2495     }
2496 }