1 /*
   2  * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /**
  25  * @test
  26  * @bug 4064654 4374886 4984320 4984574 4944795 8210142
  27  * @summary test for Calendar
  28  * @library /java/text/testlib
  29  * @modules java.base/java.util:+open
  30  * @run junit CalendarTest
  31  * @key randomness
  32  */
  33 
  34 import java.io.File;
  35 import java.io.FileInputStream;
  36 import java.io.FileOutputStream;
  37 import java.io.IOException;
  38 import java.io.ObjectInputStream;
  39 import java.io.ObjectOutput;
  40 import java.io.ObjectOutputStream;
  41 import java.lang.reflect.Field;
  42 import java.util.Calendar;
  43 import java.util.Date;
  44 import java.util.GregorianCalendar;
  45 import java.util.Locale;
  46 import java.util.SimpleTimeZone;
  47 import java.util.TimeZone;
  48 
  49 import static java.util.Calendar.*;
  50 
  51 import org.junit.jupiter.api.Test;
  52 
  53 import static org.junit.jupiter.api.Assertions.fail;
  54 
  55 public class CalendarTest {
  56 
  57     static final int ONE_DAY = 24 * 60 * 60 * 1000;
  58     static final int EPOCH_JULIAN = 2440588;
  59 
  60     /**
  61      * Test the behavior of the GregorianCalendar around the changeover.
  62      */
  63     @Test
  64     public void TestGregorianChangeover() {
  65         TimeZone savedZone = TimeZone.getDefault();
  66         /*
  67           Changeover -7 days: 1582/9/28 dow=6
  68           Changeover -6 days: 1582/9/29 dow=7
  69           Changeover -5 days: 1582/9/30 dow=1
  70           Changeover -4 days: 1582/10/1 dow=2
  71           Changeover -3 days: 1582/10/2 dow=3
  72           Changeover -2 days: 1582/10/3 dow=4
  73           Changeover -1 days: 1582/10/4 dow=5
  74           Changeover +0 days: 1582/10/15 dow=6
  75           Changeover +1 days: 1582/10/16 dow=7
  76           Changeover +2 days: 1582/10/17 dow=1
  77           Changeover +3 days: 1582/10/18 dow=2
  78           Changeover +4 days: 1582/10/19 dow=3
  79           Changeover +5 days: 1582/10/20 dow=4
  80           Changeover +6 days: 1582/10/21 dow=5
  81           Changeover +7 days: 1582/10/22 dow=6
  82           */
  83         int[] MON = {  9,  9,  9,10,10,10,10, 10, 10, 10, 10, 10, 10, 10, 10 };
  84         int[] DOM = { 28, 29, 30, 1, 2, 3, 4, 15, 16, 17, 18, 19, 20, 21, 22 };
  85         int[] DOW = {  6,  7,  1, 2, 3, 4, 5,  6,  7,  1,  2,  3,  4,  5,  6 };
  86         //                                     ^ <-Changeover Fri Oct 15 1582
  87         try {
  88             TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
  89             @SuppressWarnings("deprecation")
  90             Date co = new Date(1582 - 1900, OCTOBER, 15);
  91             GregorianCalendar cal = new GregorianCalendar();
  92             int j = 0;
  93             for (int i = -7; i <= 7; ++i, ++j) {
  94                 Date d = new Date(co.getTime() + i * ONE_DAY);
  95                 cal.setTime(d);
  96                 int y = cal.get(YEAR);
  97                 int mon = cal.get(MONTH) + 1 - JANUARY;
  98                 int dom = cal.get(DATE);
  99                 int dow = cal.get(DAY_OF_WEEK);
 100 
 101                 System.out.println("Changeover " + (i >= 0 ? "+" : "") + i
 102                         + " days: " + y + "/" + mon + "/" + dom + " dow=" + dow);
 103                 if (y != 1582 || mon != MON[j] || dom != DOM[j] || dow != DOW[j]) {
 104                     fail(" Fail: Above line is wrong");
 105                 }
 106             }
 107         } finally {
 108             TimeZone.setDefault(savedZone);
 109         }
 110     }
 111 
 112     /**
 113      * Test the mapping between millis and fields.  For the purposes
 114      * of this test, we don't care about timezones and week data
 115      * (first day of week, minimal days in first week).
 116      */
 117     @SuppressWarnings("deprecation")
 118     @Test
 119     public void TestMapping() {
 120         TimeZone saveZone = TimeZone.getDefault();
 121         int[] DATA = {
 122             // Julian#   Year      Month    DOM   JULIAN:Year  Month,   DOM
 123             2440588,     1970,    JANUARY,   1,    1969,     DECEMBER,  19,
 124             2415080,     1900,      MARCH,   1,    1900,     FEBRUARY,  17,
 125             2451604,     2000,   FEBRUARY,  29,    2000,     FEBRUARY,  16,
 126             2452269,     2001,   DECEMBER,  25,    2001,     DECEMBER,  12,
 127             2416526,     1904,   FEBRUARY,  15,    1904,     FEBRUARY,   2,
 128             2416656,     1904,       JUNE,  24,    1904,         JUNE,  11,
 129             1721426,        1,    JANUARY,   1,       1,      JANUARY,   3,
 130             2000000,      763,  SEPTEMBER,  18,     763,    SEPTEMBER,  14,
 131             4000000,     6239,       JULY,  12,    6239,          MAY,  28,
 132             8000000,    17191,   FEBRUARY,  26,   17190,      OCTOBER,  22,
 133            10000000,    22666,   DECEMBER,  20,   22666,         JULY,   5};
 134 
 135         try {
 136             TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
 137             Date PURE_GREGORIAN = new Date(Long.MIN_VALUE);
 138             Date PURE_JULIAN = new Date(Long.MAX_VALUE);
 139             GregorianCalendar cal = new GregorianCalendar();
 140             for (int i = 0; i < DATA.length; i += 7) {
 141                 int julian = DATA[i];
 142                 int year = DATA[i + 1];
 143                 int month = DATA[i + 2];
 144                 int dom = DATA[i + 3];
 145                 int year2, month2, dom2;
 146                 long millis = ((long) julian - EPOCH_JULIAN) * ONE_DAY;
 147                 String s;
 148 
 149                 // Test Gregorian computation
 150                 cal.setGregorianChange(PURE_GREGORIAN);
 151                 cal.clear();
 152                 cal.set(year, month, dom);
 153                 long calMillis = cal.getTime().getTime();
 154                 long delta = calMillis - millis;
 155                 cal.setTime(new Date(millis));
 156                 year2 = cal.get(YEAR);
 157                 month2 = cal.get(MONTH);
 158                 dom2 = cal.get(DAY_OF_MONTH);
 159                 s = "G " + year + "-" + (month + 1 - JANUARY) + "-" + dom
 160                         + " => " + calMillis
 161                         + " (" + ((float) delta / ONE_DAY) + " day delta) => "
 162                         + year2 + "-" + (month2 + 1 - JANUARY) + "-" + dom2;
 163                 if (delta != 0 || year != year2 || month != month2
 164                         || dom != dom2) {
 165                     fail(s + " FAIL");
 166                 } else {
 167                     System.out.println(s);
 168                 }
 169 
 170                 // Test Julian computation
 171                 year = DATA[i + 4];
 172                 month = DATA[i + 5];
 173                 dom = DATA[i + 6];
 174                 cal.setGregorianChange(PURE_JULIAN);
 175                 cal.clear();
 176                 cal.set(year, month, dom);
 177                 calMillis = cal.getTime().getTime();
 178                 delta = calMillis - millis;
 179                 cal.setTime(new Date(millis));
 180                 year2 = cal.get(YEAR);
 181                 month2 = cal.get(MONTH);
 182                 dom2 = cal.get(DAY_OF_MONTH);
 183                 s = "J " + year + "-" + (month + 1 - JANUARY) + "-" + dom
 184                         + " => " + calMillis
 185                         + " (" + ((float) delta / ONE_DAY) + " day delta) => "
 186                         + year2 + "-" + (month2 + 1 - JANUARY) + "-" + dom2;
 187                 if (delta != 0 || year != year2 || month != month2
 188                         || dom != dom2) {
 189                     fail(s + " FAIL");
 190                 } else {
 191                     System.out.println(s);
 192                 }
 193             }
 194 
 195             cal.setGregorianChange(new Date(1582 - 1900, OCTOBER, 15));
 196             auxMapping(cal, 1582, OCTOBER, 4);
 197             auxMapping(cal, 1582, OCTOBER, 15);
 198             auxMapping(cal, 1582, OCTOBER, 16);
 199             for (int y = 800; y < 3000; y += 1 + 100 * Math.random()) {
 200                 for (int m = JANUARY; m <= DECEMBER; ++m) {
 201                     auxMapping(cal, y, m, 15);
 202                 }
 203             }
 204         } finally {
 205             TimeZone.setDefault(saveZone);
 206         }
 207     }
 208     private void auxMapping(Calendar cal, int y, int m, int d) {
 209         cal.clear();
 210         cal.set(y, m, d);
 211         long millis = cal.getTime().getTime();
 212         cal.setTime(new Date(millis));
 213         int year2 = cal.get(YEAR);
 214         int month2 = cal.get(MONTH);
 215         int dom2 = cal.get(DAY_OF_MONTH);
 216         if (y != year2 || m != month2 || dom2 != d) {
 217             fail("Round-trip failure: " + y + "-" + (m + 1) + "-" + d + " =>ms=> "
 218                     + year2 + "-" + (month2 + 1) + "-" + dom2);
 219         }
 220     }
 221 
 222     @SuppressWarnings("deprecation")
 223     @Test
 224     public void TestGenericAPI() {
 225         Locale locale = Locale.getDefault();
 226         if (!TestUtils.usesGregorianCalendar(locale)) {
 227             System.out.println("Skipping this test because locale is " + locale);
 228             return;
 229         }
 230 
 231         String str;
 232         Date when = new Date(90, APRIL, 15);
 233 
 234         String tzid = "TestZone";
 235         int tzoffset = 123400;
 236 
 237         SimpleTimeZone zone = new SimpleTimeZone(tzoffset, tzid);
 238         Calendar cal = Calendar.getInstance((SimpleTimeZone) zone.clone());
 239 
 240         if (!zone.equals(cal.getTimeZone())) {
 241             fail("FAIL: Calendar.getTimeZone failed");
 242         }
 243 
 244         Calendar cal2 = Calendar.getInstance(cal.getTimeZone());
 245 
 246         cal.setTime(when);
 247         cal2.setTime(when);
 248 
 249         if (!(cal.equals(cal2))) {
 250             fail("FAIL: Calendar.operator== failed");
 251         }
 252         // if ((*cal != *cal2))  errln("FAIL: Calendar.operator!= failed");
 253         if (!cal.equals(cal2)
 254                 || cal.before(cal2)
 255                 || cal.after(cal2)) {
 256             fail("FAIL: equals/before/after failed");
 257         }
 258 
 259         cal2.setTime(new Date(when.getTime() + 1000));
 260         if (cal.equals(cal2)
 261                 || cal2.before(cal)
 262                 || cal.after(cal2)) {
 263             fail("FAIL: equals/before/after failed");
 264         }
 265 
 266         cal.roll(SECOND, true);
 267         if (!cal.equals(cal2)
 268                 || cal.before(cal2)
 269                 || cal.after(cal2)) {
 270             fail("FAIL: equals/before/after failed");
 271         }
 272 
 273         // Roll back to January
 274         cal.roll(MONTH, 1 + DECEMBER - cal.get(MONTH));
 275         if (cal.equals(cal2)
 276                 || cal2.before(cal)
 277                 || cal.after(cal2)) {
 278             fail("FAIL: equals/before/after failed");
 279         }
 280 
 281         // C++ only
 282         /* TimeZone z = cal.orphanTimeZone();
 283         if (z.getID(str) != tzid ||
 284         z.getRawOffset() != tzoffset)
 285         fail("FAIL: orphanTimeZone failed");
 286         */
 287         for (int i = 0; i < 2; ++i) {
 288             boolean lenient = (i > 0);
 289             cal.setLenient(lenient);
 290             if (lenient != cal.isLenient()) {
 291                 fail("FAIL: setLenient/isLenient failed");
 292             }
 293             // Later: Check for lenient behavior
 294         }
 295 
 296         int i;
 297         for (i = SUNDAY; i <= SATURDAY; ++i) {
 298             cal.setFirstDayOfWeek(i);
 299             if (cal.getFirstDayOfWeek() != i) {
 300                 fail("FAIL: set/getFirstDayOfWeek failed");
 301             }
 302         }
 303 
 304         for (i = 0; i <= 7; ++i) {
 305             cal.setMinimalDaysInFirstWeek(i);
 306             if (cal.getMinimalDaysInFirstWeek() != i) {
 307                 fail("FAIL: set/getFirstDayOfWeek failed");
 308             }
 309         }
 310 
 311         for (i = 0; i < FIELD_COUNT; ++i) {
 312             if (cal.getMinimum(i) != cal.getGreatestMinimum(i)) {
 313                 fail("FAIL: getMinimum doesn't match getGreatestMinimum for field " + i);
 314             }
 315             if (cal.getLeastMaximum(i) > cal.getMaximum(i)) {
 316                 fail("FAIL: getLeastMaximum larger than getMaximum for field " + i);
 317             }
 318             if (cal.getMinimum(i) >= cal.getMaximum(i)) {
 319                 fail("FAIL: getMinimum not less than getMaximum for field " + i);
 320             }
 321         }
 322 
 323         cal.setTimeZone(TimeZone.getDefault());
 324         cal.clear();
 325         cal.set(1984, 5, 24);
 326         if (cal.getTime().getTime() != new Date(84, 5, 24).getTime()) {
 327             fail("FAIL: Calendar.set(3 args) failed");
 328             System.out.println(" Got: " + cal.getTime() + "  Expected: " + new Date(84, 5, 24));
 329         }
 330 
 331         cal.clear();
 332         cal.set(1985, 3, 2, 11, 49);
 333         if (cal.getTime().getTime() != new Date(85, 3, 2, 11, 49).getTime()) {
 334             fail("FAIL: Calendar.set(5 args) failed");
 335             System.out.println(" Got: " + cal.getTime() + "  Expected: " + new Date(85, 3, 2, 11, 49));
 336         }
 337 
 338         cal.clear();
 339         cal.set(1995, 9, 12, 1, 39, 55);
 340         if (cal.getTime().getTime() != new Date(95, 9, 12, 1, 39, 55).getTime()) {
 341             fail("FAIL: Calendar.set(6 args) failed");
 342             System.out.println(" Got: " + cal.getTime() + "  Expected: " + new Date(95, 9, 12, 1, 39, 55));
 343         }
 344 
 345         cal.getTime();
 346         for (i = 0; i < FIELD_COUNT; ++i) {
 347             switch (i) {
 348                 case YEAR:
 349                 case MONTH:
 350                 case DATE:
 351                 case HOUR_OF_DAY:
 352                 case MINUTE:
 353                 case SECOND:
 354                     if (!cal.isSet(i)) {
 355                         fail("FAIL: !Calendar.isSet test failed: " + calendarFieldNames[i]);
 356                     }
 357                     break;
 358                 default:
 359                     if (cal.isSet(i)) {
 360                         fail("FAIL: Calendar.isSet test failed: " + calendarFieldNames[i]);
 361                     }
 362             }
 363             cal.clear(i);
 364             if (cal.isSet(i)) {
 365                 fail("FAIL: Calendar.clear/isSet failed");
 366             }
 367         }
 368 
 369         // delete cal;
 370         // delete cal2;
 371         Locale[] loc = Calendar.getAvailableLocales();
 372         long count = loc.length;
 373         if (count < 1 || loc == null) {
 374             fail("FAIL: getAvailableLocales failed");
 375         } else {
 376             for (i = 0; i < count; ++i) {
 377                 cal = Calendar.getInstance(loc[i]);
 378                 // delete cal;
 379             }
 380         }
 381 
 382         cal = Calendar.getInstance(TimeZone.getDefault(), Locale.ENGLISH);
 383         // delete cal;
 384 
 385         cal = Calendar.getInstance(zone, Locale.ENGLISH);
 386         // delete cal;
 387 
 388         GregorianCalendar gc = new GregorianCalendar(zone);
 389         // delete gc;
 390 
 391         gc = new GregorianCalendar(Locale.ENGLISH);
 392         // delete gc;
 393 
 394         gc = new GregorianCalendar(Locale.ENGLISH);
 395         // delete gc;
 396 
 397         gc = new GregorianCalendar(zone, Locale.ENGLISH);
 398         // delete gc;
 399 
 400         gc = new GregorianCalendar(zone);
 401         // delete gc;
 402 
 403         gc = new GregorianCalendar(1998, 10, 14, 21, 43);
 404         if (gc.getTime().getTime() != new Date(98, 10, 14, 21, 43).getTime()) {
 405             fail("FAIL: new GregorianCalendar(ymdhm) failed");
 406         }
 407         // delete gc;
 408 
 409         gc = new GregorianCalendar(1998, 10, 14, 21, 43, 55);
 410         if (gc.getTime().getTime() != new Date(98, 10, 14, 21, 43, 55).getTime()) {
 411             fail("FAIL: new GregorianCalendar(ymdhms) failed");
 412         }
 413 
 414         // C++ only:
 415         // GregorianCalendar gc2 = new GregorianCalendar(Locale.ENGLISH);
 416         // gc2 = gc;
 417         // if (gc2 != gc || !(gc2 == gc)) errln("FAIL: GregorianCalendar assignment/operator==/operator!= failed");
 418         // delete gc;
 419         // delete z;
 420     }
 421 
 422     // Verify Roger Webster's bug
 423     @Test
 424     public void TestRog() {
 425         GregorianCalendar gc = new GregorianCalendar();
 426 
 427         int year = 1997, month = APRIL, date = 1;
 428         gc.set(year, month, date); // April 1, 1997
 429 
 430         gc.set(HOUR_OF_DAY, 23);
 431         gc.set(MINUTE, 0);
 432         gc.set(SECOND, 0);
 433         gc.set(MILLISECOND, 0);
 434 
 435         for (int i = 0; i < 9; i++, gc.add(DATE, 1)) {
 436             if (gc.get(YEAR) != year
 437                     || gc.get(MONTH) != month
 438                     || gc.get(DATE) != (date + i)) {
 439                 fail("FAIL: Date " + gc.getTime() + " wrong");
 440             }
 441         }
 442     }
 443 
 444     // Verify DAY_OF_WEEK
 445     @Test
 446     public void TestDOW943() {
 447         dowTest(false);
 448         dowTest(true);
 449     }
 450 
 451     void dowTest(boolean lenient) {
 452         GregorianCalendar cal = new GregorianCalendar();
 453         cal.set(1997, AUGUST, 12); // Wednesday
 454         cal.getTime(); // Force update
 455         cal.setLenient(lenient);
 456         cal.set(1996, DECEMBER, 1); // Set the date to be December 1, 1996
 457         int dow = cal.get(DAY_OF_WEEK);
 458         int min = cal.getMinimum(DAY_OF_WEEK);
 459         int max = cal.getMaximum(DAY_OF_WEEK);
 460         if (dow < min || dow > max) {
 461             fail("FAIL: Day of week " + dow + " out of range");
 462         }
 463         if (dow != SUNDAY) {
 464             fail("FAIL2: Day of week should be SUNDAY; is " + dow + ": " + cal.getTime());
 465         }
 466         if (min != SUNDAY || max != SATURDAY) {
 467             fail("FAIL: Min/max bad");
 468         }
 469     }
 470 
 471     // Verify that the clone method produces distinct objects with no
 472     // unintentionally shared fields.
 473     @Test
 474     public void TestClonesUnique908() {
 475         Calendar c = Calendar.getInstance();
 476         Calendar d = (Calendar) c.clone();
 477         c.set(MILLISECOND, 123);
 478         d.set(MILLISECOND, 456);
 479         if (c.get(MILLISECOND) != 123
 480                 || d.get(MILLISECOND) != 456) {
 481             fail("FAIL: Clones share fields");
 482         }
 483     }
 484 
 485     // Verify effect of Gregorian cutoff value
 486     @SuppressWarnings("deprecation")
 487     @Test
 488     public void TestGregorianChange768() {
 489         boolean b;
 490         GregorianCalendar c = new GregorianCalendar();
 491         System.out.println("With cutoff " + c.getGregorianChange());
 492         System.out.println(" isLeapYear(1800) = " + (b = c.isLeapYear(1800)));
 493         System.out.println(" (should be FALSE)");
 494         if (b != false) {
 495             fail("FAIL");
 496         }
 497         c.setGregorianChange(new Date(0, 0, 1)); // Jan 1 1900
 498         System.out.println("With cutoff " + c.getGregorianChange());
 499         System.out.println(" isLeapYear(1800) = " + (b = c.isLeapYear(1800)));
 500         System.out.println(" (should be TRUE)");
 501         if (b != true) {
 502             fail("FAIL");
 503         }
 504     }
 505 
 506     // Test the correct behavior of the disambiguation algorithm.
 507     @Test
 508     public void TestDisambiguation765() throws Exception {
 509         Locale savedLocale = Locale.getDefault();
 510         try {
 511             Locale.setDefault(Locale.US);
 512             Calendar c = Calendar.getInstance();
 513             c.setLenient(false);
 514 
 515             c.clear();
 516             c.set(YEAR, 1997);
 517             c.set(MONTH, JUNE);
 518             c.set(DATE, 3);
 519 
 520             verify765("1997 third day of June = ", c, 1997, JUNE, 3);
 521 
 522             c.clear();
 523             c.set(YEAR, 1997);
 524             c.set(DAY_OF_WEEK, TUESDAY);
 525             c.set(MONTH, JUNE);
 526             c.set(DAY_OF_WEEK_IN_MONTH, 1);
 527             verify765("1997 first Tuesday in June = ", c, 1997, JUNE, 3);
 528 
 529             c.setLenient(true); // for 4944795
 530             c.clear();
 531             c.set(YEAR, 1997);
 532             c.set(DAY_OF_WEEK, TUESDAY);
 533             c.set(MONTH, JUNE);
 534             c.set(DAY_OF_WEEK_IN_MONTH, -1);
 535             verify765("1997 last Tuesday in June = ", c, 1997, JUNE, 24);
 536 
 537             c.setLenient(false);
 538             IllegalArgumentException e = null;
 539             try {
 540                 c.clear();
 541                 c.set(YEAR, 1997);
 542                 c.set(DAY_OF_WEEK, TUESDAY);
 543                 c.set(MONTH, JUNE);
 544                 c.set(DAY_OF_WEEK_IN_MONTH, 0);
 545                 c.getTime();
 546             } catch (IllegalArgumentException ex) {
 547                 e = ex;
 548             }
 549             verify765("1997 zero-th Tuesday in June = ", e);
 550 
 551             c.clear();
 552             c.set(YEAR, 1997);
 553             c.set(DAY_OF_WEEK, TUESDAY);
 554             c.set(MONTH, JUNE);
 555             c.set(WEEK_OF_MONTH, 1);
 556             verify765("1997 Tuesday in week 1 of June = ", c, 1997, JUNE, 3);
 557 
 558             c.clear();
 559             c.set(YEAR, 1997);
 560             c.set(DAY_OF_WEEK, TUESDAY);
 561             c.set(MONTH, JUNE);
 562             c.set(WEEK_OF_MONTH, 4);
 563             verify765("1997 Tuesday in week 4 of June = ", c, 1997, JUNE, 24);
 564 
 565             try {
 566                 c.clear();
 567                 c.set(YEAR, 1997);
 568                 c.set(DAY_OF_WEEK, TUESDAY);
 569                 c.set(MONTH, JUNE);
 570                 c.set(WEEK_OF_MONTH, 1);
 571                 verify765("1997 Tuesday in week 0 of June = ", c, 1997, JUNE, 3);
 572             } catch (IllegalArgumentException ex) {
 573                 fail("FAIL: Exception seen: " + ex.getMessage());
 574                 // ex.printStackTrace(log);
 575             }
 576 
 577             c.clear();
 578             c.set(YEAR, 1997);
 579             c.set(DAY_OF_WEEK, TUESDAY);
 580             c.set(WEEK_OF_YEAR, 2);
 581             verify765("1997 Tuesday in week 2 of year = ", c, 1997, JANUARY, 7);
 582 
 583             c.clear();
 584             c.set(YEAR, 1997);
 585             c.set(DAY_OF_WEEK, TUESDAY);
 586             c.set(WEEK_OF_YEAR, 10);
 587             verify765("1997 Tuesday in week 10 of year = ", c, 1997, MARCH, 4);
 588 
 589             try {
 590                 c.clear();
 591                 c.set(YEAR, 1997);
 592                 c.set(DAY_OF_WEEK, TUESDAY);
 593                 c.set(WEEK_OF_YEAR, 0);
 594                 verify765("1997 Tuesday in week 0 of year = ", c, 1996, DECEMBER, 24);
 595                 throw new Exception("Fail: WEEK_OF_YEAR 0 should be illegal");
 596             } catch (IllegalArgumentException ex) {
 597             }
 598         } finally {
 599             Locale.setDefault(savedLocale);
 600         }
 601     }
 602 
 603     void verify765(String msg, Calendar c, int year, int month, int day) {
 604         if (c.get(YEAR) == year
 605                 && c.get(MONTH) == month
 606                 && c.get(DATE) == day) {
 607             System.out.println("PASS: " + msg + c.getTime());
 608         } else {
 609             fail("FAIL: " + msg + c.getTime()
 610                     + "; expected "
 611                     + year + "/" + (month + 1) + "/" + day);
 612         }
 613     }
 614 
 615     // Called when e expected to be non-null
 616     void verify765(String msg, IllegalArgumentException e) {
 617         if (e == null) {
 618             fail("FAIL: No IllegalArgumentException for " + msg);
 619         } else {
 620             System.out.println("PASS: " + msg + "IllegalArgument as expected");
 621         }
 622     }
 623 
 624     // Test the behavior of GMT vs. local time
 625     @Test
 626     public void TestGMTvsLocal4064654() {
 627         Locale locale = Locale.getDefault();
 628         if (!TestUtils.usesGregorianCalendar(locale)) {
 629             System.out.println("Skipping this test because locale is " + locale);
 630             return;
 631         }
 632 
 633         // Sample output 1:
 634         // % /usr/local/java/jdk1.1.3/solaris/bin/java test 1997 1 1 12 0 0
 635         // date = Wed Jan 01 04:00:00 PST 1997
 636         // offset for Wed Jan 01 04:00:00 PST 1997= -8hr
 637         test4064654(1997, 1, 1, 12, 0, 0);
 638 
 639         // Sample output 2:
 640         // % /usr/local/java/jdk1.1.3/solaris/bin/java test 1997 4 16 18 30 0
 641         // date = Wed Apr 16 10:30:00 PDT 1997
 642         // offset for Wed Apr 16 10:30:00 PDT 1997= -7hr
 643 
 644         // Note that in sample output 2 according to the offset, the gmt time
 645         // of the result would be 1997 4 16 17 30 0 which is different from the
 646         // input of 1997 4 16 18 30 0.
 647         test4064654(1997, 4, 16, 18, 30, 0);
 648     }
 649     void test4064654(int yr, int mo, int dt, int hr, int mn, int sc) {
 650         Date date;
 651         Calendar gmtcal = Calendar.getInstance();
 652         gmtcal.setTimeZone(TimeZone.getTimeZone("Africa/Casablanca"));
 653         gmtcal.set(yr, mo - 1, dt, hr, mn, sc);
 654         gmtcal.set(MILLISECOND, 0);
 655 
 656         date = gmtcal.getTime();
 657         System.out.println("date = " + date);
 658 
 659         Calendar cal = Calendar.getInstance();
 660         cal.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
 661         cal.setTime(date);
 662 
 663         int offset = cal.getTimeZone().getOffset(cal.get(ERA),
 664                 cal.get(YEAR),
 665                 cal.get(MONTH),
 666                 cal.get(DATE),
 667                 cal.get(DAY_OF_WEEK),
 668                 cal.get(MILLISECOND));
 669 
 670         System.out.println("offset for " + date + "= " + (offset / 1000 / 60 / 60.0) + "hr");
 671 
 672         int utc = ((cal.get(HOUR_OF_DAY) * 60
 673                 + cal.get(MINUTE)) * 60
 674                 + cal.get(SECOND)) * 1000
 675                 + cal.get(MILLISECOND) - offset;
 676 
 677         int expected = ((hr * 60 + mn) * 60 + sc) * 1000;
 678 
 679         if (utc != expected) {
 680             fail("FAIL: Discrepancy of "
 681                     + (utc - expected) + " millis = "
 682                     + ((utc - expected) / 1000 / 60 / 60.0) + " hr");
 683         }
 684     }
 685 
 686     // Verify that add and set work regardless of the order in which
 687     // they are called.
 688     @Test
 689     public void TestAddSetOrder621() {
 690         @SuppressWarnings("deprecation")
 691         Date d = new Date(97, 4, 14, 13, 23, 45);
 692 
 693         Calendar cal = Calendar.getInstance();
 694         cal.setTime(d);
 695         cal.add(DATE, -5);
 696         cal.set(HOUR_OF_DAY, 0);
 697         cal.set(MINUTE, 0);
 698         cal.set(SECOND, 0);
 699         // ma feb 03 00:00:00 GMT+00:00 1997
 700         String s = cal.getTime().toString();
 701 
 702         cal = Calendar.getInstance();
 703         cal.setTime(d);
 704         cal.set(HOUR_OF_DAY, 0);
 705         cal.set(MINUTE, 0);
 706         cal.set(SECOND, 0);
 707         cal.add(DATE, -5);
 708         // ma feb 03 13:11:06 GMT+00:00 1997
 709         String s2 = cal.getTime().toString();
 710 
 711         if (s.equals(s2)) {
 712             System.out.println("Pass: " + s + " == " + s2);
 713         } else {
 714             fail("FAIL: " + s + " != " + s2);
 715         }
 716     }
 717 
 718     // Verify that add works.
 719     @Test
 720     public void TestAdd520() {
 721         int y = 1997, m = FEBRUARY, d = 1;
 722         GregorianCalendar temp = new GregorianCalendar(y, m, d);
 723         check520(temp, y, m, d);
 724 
 725         temp.add(YEAR, 1);
 726         y++;
 727         check520(temp, y, m, d);
 728 
 729         temp.add(MONTH, 1);
 730         m++;
 731         check520(temp, y, m, d);
 732 
 733         temp.add(DATE, 1);
 734         d++;
 735         check520(temp, y, m, d);
 736 
 737         temp.add(DATE, 2);
 738         d += 2;
 739         check520(temp, y, m, d);
 740 
 741         temp.add(DATE, 28);
 742         d = 1;
 743         ++m;
 744         check520(temp, y, m, d);
 745     }
 746 
 747     void check520(Calendar c, int y, int m, int d) {
 748         if (c.get(YEAR) != y
 749                 || c.get(MONTH) != m
 750                 || c.get(DATE) != d) {
 751             fail("FAILURE: Expected YEAR/MONTH/DATE of "
 752                     + y + "/" + (m + 1) + "/" + d
 753                     + "; got "
 754                     + c.get(YEAR) + "/"
 755                     + (c.get(MONTH) + 1) + "/"
 756                     + c.get(DATE));
 757         } else {
 758             System.out.println("Confirmed: "
 759                     + y + "/" + (m + 1) + "/" + d);
 760         }
 761     }
 762 
 763     // Verify that setting fields works.  This test fails when an exception is thrown.
 764     @Test
 765     public void TestFieldSet4781() {
 766         try {
 767             GregorianCalendar g = new GregorianCalendar();
 768             GregorianCalendar g2 = new GregorianCalendar();
 769             // At this point UTC value is set, various fields are not.
 770             // Now set to noon.
 771             g2.set(HOUR, 12);
 772             g2.set(MINUTE, 0);
 773             g2.set(SECOND, 0);
 774             // At this point the object thinks UTC is NOT set, but fields are set.
 775             // The following line will result in IllegalArgumentException because
 776             // it thinks the YEAR is set and it is NOT.
 777             if (g2.equals(g)) {
 778                 System.out.println("Same");
 779             } else {
 780                 System.out.println("Different");
 781             }
 782         } catch (IllegalArgumentException e) {
 783             fail("Unexpected exception seen: " + e);
 784         }
 785     }
 786 
 787     // Test serialization of a Calendar object
 788     @Test
 789     public void TestSerialize337() {
 790         Calendar cal = Calendar.getInstance();
 791 
 792         boolean ok = false;
 793 
 794         try {
 795             FileOutputStream f = new FileOutputStream(FILENAME);
 796             ObjectOutput s = new ObjectOutputStream(f);
 797             s.writeObject(PREFIX);
 798             s.writeObject(cal);
 799             s.writeObject(POSTFIX);
 800             f.close();
 801 
 802             FileInputStream in = new FileInputStream(FILENAME);
 803             ObjectInputStream t = new ObjectInputStream(in);
 804             String pre = (String) t.readObject();
 805             Calendar c = (Calendar) t.readObject();
 806             String post = (String) t.readObject();
 807             in.close();
 808 
 809             ok = pre.equals(PREFIX)
 810                     && post.equals(POSTFIX)
 811                     && cal.equals(c);
 812 
 813             File fl = new File(FILENAME);
 814             fl.delete();
 815         } catch (IOException e) {
 816             fail("FAIL: Exception received:");
 817             // e.printStackTrace(log);
 818         } catch (ClassNotFoundException e) {
 819             fail("FAIL: Exception received:");
 820             // e.printStackTrace(log);
 821         }
 822 
 823         if (!ok) {
 824             fail("Serialization of Calendar object failed.");
 825         }
 826     }
 827     static final String PREFIX = "abc";
 828     static final String POSTFIX = "def";
 829     static final String FILENAME = "tmp337.bin";
 830 
 831     // Try to zero out the seconds field
 832     @Test
 833     public void TestSecondsZero121() {
 834         Calendar cal = new GregorianCalendar();
 835         // Initialize with current date/time
 836         cal.setTime(new Date());
 837         // Round down to minute
 838         cal.set(SECOND, 0);
 839         Date d = cal.getTime();
 840         String s = d.toString();
 841         if (s.indexOf(":00 ") < 0) {
 842             fail("Expected to see :00 in " + s);
 843         }
 844     }
 845 
 846     // Try various sequences of add, set, and get method calls.
 847     @Test
 848     public void TestAddSetGet0610() {
 849         //
 850         // Error case 1:
 851         // - Upon initialization calendar fields, millis = System.currentTime
 852         // - After set is called fields are initialized, time is not
 853         // - Addition uses millis which are still *now*
 854         //
 855         {
 856             Calendar calendar = new GregorianCalendar();
 857             calendar.set(1993, JANUARY, 4);
 858             System.out.println("1A) " + value(calendar));
 859             calendar.add(DATE, 1);
 860             String v = value(calendar);
 861             System.out.println("1B) " + v);
 862             System.out.println("--) 1993/0/5");
 863             if (!v.equals(EXPECTED_0610)) {
 864                 fail("Expected " + EXPECTED_0610
 865                         + "; saw " + v);
 866             }
 867         }
 868 
 869         //
 870         // Error case 2:
 871         // - Upon initialization calendar fields set, millis = 0
 872         // - Addition uses millis which are still 1970, 0, 1
 873         //
 874         {
 875             Calendar calendar = new GregorianCalendar(1993, JANUARY, 4);
 876             System.out.println("2A) " + value(calendar));
 877             calendar.add(DATE, 1);
 878             String v = value(calendar);
 879             System.out.println("2B) " + v);
 880             System.out.println("--) 1993/0/5");
 881             if (!v.equals(EXPECTED_0610)) {
 882                 fail("Expected " + EXPECTED_0610
 883                         + "; saw " + v);
 884             }
 885         }
 886 
 887         //
 888         // Error case 3:
 889         // - Upon initialization calendar fields, millis = 0
 890         // - getTime( ) is called which forces the millis to be set
 891         // - Addition uses millis which are correct
 892         //
 893         {
 894             Calendar calendar = new GregorianCalendar(1993, JANUARY, 4);
 895             System.out.println("3A) " + value(calendar));
 896             calendar.getTime();
 897             calendar.add(DATE, 1);
 898             String v = value(calendar);
 899             System.out.println("3B) " + v);
 900             System.out.println("--) 1993/0/5");
 901             if (!v.equals(EXPECTED_0610)) {
 902                 fail("Expected " + EXPECTED_0610
 903                         + "; saw " + v);
 904             }
 905         }
 906     }
 907     static String value(Calendar calendar) {
 908         return (calendar.get(YEAR) + "/"
 909                 + calendar.get(MONTH) + "/"
 910                 + calendar.get(DATE));
 911     }
 912     static String EXPECTED_0610 = "1993/0/5";
 913 
 914     // Test that certain fields on a certain date are as expected.
 915     @Test
 916     public void TestFields060() {
 917         int year = 1997;
 918         int month = OCTOBER;  //october
 919         int dDate = 22;   //DAYOFWEEK should return 3 for Wednesday
 920         GregorianCalendar calendar = null;
 921 
 922         calendar = new GregorianCalendar(year, month, dDate);
 923         for (int i = 0; i < EXPECTED_FIELDS.length;) {
 924             int field = EXPECTED_FIELDS[i++];
 925             int expected = EXPECTED_FIELDS[i++];
 926             if (calendar.get(field) != expected) {
 927                 fail("Expected field " + field + " to have value " + expected
 928                         + "; received " + calendar.get(field) + " instead");
 929             }
 930         }
 931     }
 932     static int[] EXPECTED_FIELDS = {
 933         YEAR, 1997,
 934         MONTH, OCTOBER,
 935         DAY_OF_MONTH, 22,
 936         DAY_OF_WEEK, WEDNESDAY,
 937         DAY_OF_WEEK_IN_MONTH, 4,
 938         DAY_OF_YEAR, 295};
 939 
 940     static final String[] calendarFieldNames = {
 941         /*  0 */ "ERA",
 942         /*  1 */ "YEAR",
 943         /*  2 */ "MONTH",
 944         /*  3 */ "WEEK_OF_YEAR",
 945         /*  4 */ "WEEK_OF_MONTH",
 946         /*  5 */ "DAY_OF_MONTH",
 947         /*  6 */ "DAY_OF_YEAR",
 948         /*  7 */ "DAY_OF_WEEK",
 949         /*  8 */ "DAY_OF_WEEK_IN_MONTH",
 950         /*  9 */ "AM_PM",
 951         /* 10 */ "HOUR",
 952         /* 11 */ "HOUR_OF_DAY",
 953         /* 12 */ "MINUTE",
 954         /* 13 */ "SECOND",
 955         /* 14 */ "MILLISECOND",
 956         /* 15 */ "ZONE_OFFSET",
 957         /* 16 */ "DST_OFFSET"};
 958 
 959     // Verify that the fields are as expected (mostly zero) at the epoch start.
 960     // Note that we adjust for the default timezone to get most things to zero.
 961     @Test
 962     public void TestEpochStartFields() {
 963         String[][] lt = {
 964             {"en", "US", "US/Pacific"},        /* First day = 1, Minimum day = 1 */
 965             {"en", "US", "America/Anchorage"}, /* First day = 1, Minimum day = 1 */
 966             {"en", "TO", "Pacific/Tongatapu"}, /* First day = 1, Minimum day = 1 */
 967             {"en", "MH", "Pacific/Majuro"},    /* First day = 1, Minimum day = 1 */
 968             {"ja", "JP", "Asia/Tokyo"},        /* First day = 1, Minimum day = 1 */
 969             {"iw", "IL", "Asia/Jerusalem"},    /* First day = 1, Minimum day = 1 */
 970             {"hi", "IN", "Asia/Jakarta"},      /* First day = 1, Minimum day = 1 */
 971             {"en", "GB", "Europe/London"},     /* First day = 2, Minimum day = 1 */
 972             {"en", "GB", "GMT"},               /* First day = 2, Minimum day = 1 */
 973             {"de", "DE", "Europe/Berlin"},     /* First day = 2, Minimum day = 4 */
 974             {"ar", "EG", "Africa/Cairo"}};     /* First day = 7, Minimum day = 1 */
 975 
 976         int[][] goldenData = {
 977             {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, -28800000, 0},
 978             {1, 1969, 11, 1, 5, 31, 365, 4, 5, 1, 11, 23, 0, 0, 0, -36000000, 0},
 979             {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 46800000, 0},
 980             {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 43200000, 0},
 981             {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 32400000, 0},
 982             {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 7200000, 0},
 983             {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 25200000, 0},
 984             {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 1, 1, 0, 0, 0, 3600000, 0},
 985             {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0},
 986             {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 3600000, 0},
 987             {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 7200000, 0}};
 988 
 989         Locale savedLocale = Locale.getDefault();
 990         TimeZone savedTimeZone = TimeZone.getDefault();
 991 
 992         try {
 993             for (int j = 0; j < lt.length; j++) {
 994                 Locale l = Locale.of(lt[j][0], lt[j][1]);
 995                 TimeZone z = TimeZone.getTimeZone(lt[j][2]);
 996                 Locale.setDefault(l);
 997                 TimeZone.setDefault(z);
 998                 Calendar c = Calendar.getInstance();
 999                 Date d = new Date(-z.getRawOffset());
1000 
1001                 int val;
1002                 int[] EPOCH_FIELDS = goldenData[j];
1003                 c.setTime(d);
1004 
1005                 boolean err = false;
1006                 for (int i = 0; i < calendarFieldNames.length; ++i) {
1007                     if ((val = c.get(i)) != EPOCH_FIELDS[i]) {
1008                         fail("Wrong value: " + val
1009                                 + " for field(" + calendarFieldNames[i]
1010                                 + "), expected: " + EPOCH_FIELDS[i]);
1011                         err = true;
1012                     }
1013                 }
1014                 if (err) {
1015                     fail("Failed: \n\tDate=" + d + "\n\tTimeZone=" + z
1016                             + "\n\tLocale=" + l + "\n\tCalendar=" + c);
1017                 }
1018             }
1019         } finally {
1020             Locale.setDefault(savedLocale);
1021             TimeZone.setDefault(savedTimeZone);
1022         }
1023     }
1024 
1025     // Verify that as you add days to the calendar (e.g., 24 day periods),
1026     // the day of the week shifts in the expected pattern.
1027     @Test
1028     public void TestDOWProgression() {
1029         Calendar cal
1030                 = new GregorianCalendar(1972, OCTOBER, 26);
1031         marchByDelta(cal, 24); // Last parameter must be != 0 modulo 7
1032     }
1033 
1034     // Supply a delta which is not a multiple of 7.
1035     void marchByDelta(Calendar cal, int delta) {
1036         Calendar cur = (Calendar) cal.clone();
1037         int initialDOW = cur.get(DAY_OF_WEEK);
1038         int DOW, newDOW = initialDOW;
1039         do {
1040             DOW = newDOW;
1041             System.out.println("DOW = " + DOW + "  " + cur.getTime());
1042 
1043             cur.add(DAY_OF_WEEK, delta);
1044             newDOW = cur.get(DAY_OF_WEEK);
1045             int expectedDOW = 1 + (DOW + delta - 1) % 7;
1046             if (newDOW != expectedDOW) {
1047                 fail("Day of week should be " + expectedDOW
1048                         + " instead of " + newDOW + " on " + cur.getTime());
1049                 return;
1050             }
1051         } while (newDOW != initialDOW);
1052     }
1053 
1054     @Test
1055     public void TestActualMinMax() {
1056         Calendar cal = new GregorianCalendar(1967, MARCH, 10);
1057         cal.setFirstDayOfWeek(SUNDAY);
1058         cal.setMinimalDaysInFirstWeek(3);
1059 
1060         if (cal.getActualMinimum(DAY_OF_MONTH) != 1) {
1061             fail("Actual minimum date for 3/10/1967 should have been 1; got "
1062                     + cal.getActualMinimum(DAY_OF_MONTH));
1063         }
1064         if (cal.getActualMaximum(DAY_OF_MONTH) != 31) {
1065             fail("Actual maximum date for 3/10/1967 should have been 31; got "
1066                     + cal.getActualMaximum(DAY_OF_MONTH));
1067         }
1068 
1069         cal.set(MONTH, FEBRUARY);
1070         if (cal.getActualMaximum(DAY_OF_MONTH) != 28) {
1071             fail("Actual maximum date for 2/10/1967 should have been 28; got "
1072                     + cal.getActualMaximum(DAY_OF_MONTH));
1073         }
1074         if (cal.getActualMaximum(DAY_OF_YEAR) != 365) {
1075             fail("Number of days in 1967 should have been 365; got "
1076                     + cal.getActualMaximum(DAY_OF_YEAR));
1077         }
1078 
1079         cal.set(YEAR, 1968);
1080         if (cal.getActualMaximum(DAY_OF_MONTH) != 29) {
1081             fail("Actual maximum date for 2/10/1968 should have been 29; got "
1082                     + cal.getActualMaximum(DAY_OF_MONTH));
1083         }
1084         if (cal.getActualMaximum(DAY_OF_YEAR) != 366) {
1085             fail("Number of days in 1968 should have been 366; got "
1086                     + cal.getActualMaximum(DAY_OF_YEAR));
1087         }
1088         // Using week settings of SUNDAY/3 (see above)
1089         if (cal.getActualMaximum(WEEK_OF_YEAR) != 52) {
1090             fail("Number of weeks in 1968 should have been 52; got "
1091                     + cal.getActualMaximum(WEEK_OF_YEAR));
1092         }
1093 
1094         cal.set(YEAR, 1976);
1095         // Using week settings of SUNDAY/3 (see above)
1096         if (cal.getActualMaximum(WEEK_OF_YEAR) != 53) {
1097             fail("Number of weeks in 1976 should have been 53; got "
1098                     + cal.getActualMaximum(WEEK_OF_YEAR));
1099         }
1100     }
1101 
1102     @Test
1103     public void TestRoll() {
1104         Calendar cal = new GregorianCalendar(1997, JANUARY, 31);
1105 
1106         int[] dayValues = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31};
1107 
1108         for (int i = 0; i < dayValues.length; i++) {
1109             Calendar cal2 = (Calendar) cal.clone();
1110             cal2.roll(MONTH, i);
1111             if (cal2.get(DAY_OF_MONTH) != dayValues[i]) {
1112                 fail("Rolling the month in 1/31/1997 up by " + i + " should have yielded "
1113                         + ((i + 1) % 12) + "/" + dayValues[i] + "/1997, but actually yielded "
1114                         + ((i + 1) % 12) + "/" + cal2.get(DAY_OF_MONTH) + "/1997.");
1115             }
1116         }
1117 
1118         cal.set(1996, FEBRUARY, 29);
1119 
1120         int[] monthValues = {1, 2, 2, 2, 1, 2, 2, 2, 1, 2};
1121         int[] dayValues2 = {29, 1, 1, 1, 29, 1, 1, 1, 29, 1};
1122 
1123         for (int i = 0; i < dayValues2.length; i++) {
1124             Calendar cal2 = (Calendar) cal.clone();
1125             cal2.roll(YEAR, i);
1126             if (cal2.get(DAY_OF_MONTH) != dayValues2[i] || cal2.get(MONTH)
1127                     != monthValues[i]) {
1128                 fail("Rolling the year in 2/29/1996 up by " + i + " should have yielded "
1129                         + (monthValues[i] + 1) + "/" + dayValues2[i] + "/"
1130                         + (1996 + i) + ", but actually yielded "
1131                         + (cal2.get(MONTH) + 1) + "/"
1132                         + cal2.get(DAY_OF_MONTH) + "/" + (1996 + i) + ".");
1133             }
1134         }
1135 
1136         // Test rolling hour of day
1137         cal.set(HOUR_OF_DAY, 0);
1138         cal.roll(HOUR_OF_DAY, -2);
1139         int f = cal.get(HOUR_OF_DAY);
1140         if (f != 22) {
1141             fail("Rolling HOUR_OF_DAY=0 delta=-2 gave " + f + " Wanted 22");
1142         }
1143         cal.roll(HOUR_OF_DAY, 5);
1144         f = cal.get(HOUR_OF_DAY);
1145         if (f != 3) {
1146             fail("Rolling HOUR_OF_DAY=22 delta=5 gave " + f + " Wanted 3");
1147         }
1148         cal.roll(HOUR_OF_DAY, 21);
1149         f = cal.get(HOUR_OF_DAY);
1150         if (f != 0) {
1151             fail("Rolling HOUR_OF_DAY=3 delta=21 gave " + f + " Wanted 0");
1152         }
1153 
1154         // Test rolling hour
1155         cal.set(HOUR_OF_DAY, 0);
1156         cal.roll(HOUR, -2);
1157         f = cal.get(HOUR);
1158         if (f != 10) {
1159             fail("Rolling HOUR=0 delta=-2 gave " + f + " Wanted 10");
1160         }
1161         cal.roll(HOUR, 5);
1162         f = cal.get(HOUR);
1163         if (f != 3) {
1164             fail("Rolling HOUR=10 delta=5 gave " + f + " Wanted 3");
1165         }
1166         cal.roll(HOUR, 9);
1167         f = cal.get(HOUR);
1168         if (f != 0) {
1169             fail("Rolling HOUR=3 delta=9 gave " + f + " Wanted 0");
1170         }
1171     }
1172 
1173     /*
1174      * Confirm that multiple calls to Calendar.set() works correctly.
1175      */
1176     @Test
1177     public void Test4374886() {
1178         Locale savedLocale = Locale.getDefault();
1179         TimeZone savedTimeZone = TimeZone.getDefault();
1180 
1181         try {
1182             Locale.setDefault(Locale.US);
1183             TimeZone.setDefault(TimeZone.getTimeZone("PST"));
1184 
1185             Calendar cal = Calendar.getInstance();
1186             cal.set(YEAR, 2001);
1187             cal.set(MONTH, OCTOBER);
1188             cal.set(WEEK_OF_YEAR, 4);
1189             cal.set(DAY_OF_WEEK, 2);
1190 
1191             if (cal.get(YEAR) != 2001
1192                     || cal.get(MONTH) != JANUARY
1193                     || cal.get(DATE) != 22
1194                     || cal.get(DAY_OF_WEEK) != MONDAY) {
1195                 fail("Failed : got " + cal.getTime() + ", expected Mon Jan 22, 2001");
1196             }
1197         } finally {
1198             Locale.setDefault(savedLocale);
1199             TimeZone.setDefault(savedTimeZone);
1200         }
1201     }
1202 
1203     @Test
1204     public void TestClonedSharedZones() throws NoSuchFieldException, IllegalAccessException {
1205         Field zone = Calendar.class.getDeclaredField("zone");
1206         zone.setAccessible(true);
1207         Field sharedZone = Calendar.class.getDeclaredField("sharedZone");
1208         sharedZone.setAccessible(true);
1209 
1210         // create a new calendar with any date, and clone it.
1211         Calendar c1 = new GregorianCalendar();
1212         Calendar c2 = (Calendar) c1.clone();
1213 
1214         // c1 should have a shared zone
1215         if (!sharedZone.getBoolean(c1)) {
1216             fail("Failed : c1.sharedZone == false");
1217         } else {
1218             // c2 should have a shared zone too
1219             if (!sharedZone.getBoolean(c2)) {
1220                 fail("Failed : c2.sharedZone == false");
1221             } else if (zone.get(c1) != zone.get(c2)) {
1222                 fail("Failed : c1.zone != c2.zone");
1223             }
1224         }
1225     }
1226 }
1227 
1228 //eof