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