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