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