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