1 /* GENERATED SOURCE. DO NOT MODIFY. */ 2 // © 2016 and later: Unicode, Inc. and others. 3 // License & terms of use: http://www.unicode.org/copyright.html#License 4 /* 5 ******************************************************************************* 6 * Copyright (C) 2000-2016, International Business Machines Corporation and 7 * others. All Rights Reserved. 8 ******************************************************************************* 9 */ 10 package ohos.global.icu.dev.test.calendar; 11 12 import java.text.FieldPosition; 13 import java.text.ParseException; 14 import java.util.Date; 15 import java.util.Locale; 16 import java.util.Set; 17 18 import org.junit.Test; 19 import org.junit.runner.RunWith; 20 import org.junit.runners.JUnit4; 21 22 import ohos.global.icu.impl.CalendarAstronomer; 23 import ohos.global.icu.impl.LocaleUtility; 24 import ohos.global.icu.impl.ZoneMeta; 25 import ohos.global.icu.text.DateFormat; 26 import ohos.global.icu.text.DateFormatSymbols; 27 import ohos.global.icu.text.SimpleDateFormat; 28 import ohos.global.icu.util.BuddhistCalendar; 29 import ohos.global.icu.util.Calendar; 30 import ohos.global.icu.util.ChineseCalendar; 31 import ohos.global.icu.util.GregorianCalendar; 32 import ohos.global.icu.util.JapaneseCalendar; 33 import ohos.global.icu.util.TaiwanCalendar; 34 import ohos.global.icu.util.TimeZone; 35 import ohos.global.icu.util.TimeZone.SystemTimeZoneType; 36 import ohos.global.icu.util.ULocale; 37 38 39 /** 40 * @summary Tests of new functionality in IBMCalendar 41 */ 42 43 @RunWith(JUnit4.class) 44 public class IBMCalendarTest extends CalendarTestFmwk { 45 /** 46 * Test weekend support in IBMCalendar. 47 * 48 * NOTE: This test will have to be updated when the isWeekend() etc. 49 * API is finalized later. 50 * 51 * In particular, the test will have to be rewritten to instantiate 52 * a Calendar in the given locale (using getInstance()) and call 53 * that Calendar's isWeekend() etc. methods. 54 */ 55 @Test TestWeekend()56 public void TestWeekend() { 57 SimpleDateFormat fmt = new SimpleDateFormat("EEE MMM dd yyyy G HH:mm:ss.SSS"); 58 59 // NOTE 60 // This test tests for specific locale data. This is probably okay 61 // as far as US data is concerned, but if the Arabic/Yemen data 62 // changes, this test will have to be updated. 63 64 // Test specific days 65 Object[] DATA1 = { 66 Locale.US, new int[] { // Saturday:Sunday 67 2000, Calendar.MARCH, 17, 23, 0, 0, // Fri 23:00 68 2000, Calendar.MARCH, 18, 0, -1, 0, // Fri 23:59:59.999 69 2000, Calendar.MARCH, 18, 0, 0, 1, // Sat 00:00 70 2000, Calendar.MARCH, 18, 15, 0, 1, // Sat 15:00 71 2000, Calendar.MARCH, 19, 23, 0, 1, // Sun 23:00 72 2000, Calendar.MARCH, 20, 0, -1, 1, // Sun 23:59:59.999 73 2000, Calendar.MARCH, 20, 0, 0, 0, // Mon 00:00 74 2000, Calendar.MARCH, 20, 8, 0, 0, // Mon 08:00 75 }, 76 new Locale("ar", "OM"), new int[] { // Friday:Saturday 77 2000, Calendar.MARCH, 15, 23, 0, 0, // Wed 23:00 78 2000, Calendar.MARCH, 16, 0, -1, 0, // Wed 23:59:59.999 79 2000, Calendar.MARCH, 16, 0, 0, 0, // Thu 00:00 80 2000, Calendar.MARCH, 16, 15, 0, 0, // Thu 15:00 81 2000, Calendar.MARCH, 17, 23, 0, 1, // Fri 23:00 82 2000, Calendar.MARCH, 18, 0, -1, 1, // Fri 23:59:59.999 83 2000, Calendar.MARCH, 18, 0, 0, 1, // Sat 00:00 84 2000, Calendar.MARCH, 18, 8, 0, 1, // Sat 08:00 85 }, 86 }; 87 88 // Test days of the week 89 Object[] DATA2 = { 90 Locale.US, new int[] { 91 Calendar.MONDAY, Calendar.WEEKDAY, 92 Calendar.FRIDAY, Calendar.WEEKDAY, 93 Calendar.SATURDAY, Calendar.WEEKEND, 94 Calendar.SUNDAY, Calendar.WEEKEND, 95 }, 96 new Locale("ar", "OM"), new int[] { // Friday:Saturday 97 Calendar.WEDNESDAY,Calendar.WEEKDAY, 98 Calendar.THURSDAY, Calendar.WEEKDAY, 99 Calendar.FRIDAY, Calendar.WEEKEND, 100 Calendar.SATURDAY, Calendar.WEEKEND, 101 }, 102 new Locale("hi", "IN"), new int[] { // Sunday only 103 Calendar.MONDAY, Calendar.WEEKDAY, 104 Calendar.FRIDAY, Calendar.WEEKDAY, 105 Calendar.SATURDAY, Calendar.WEEKDAY, 106 Calendar.SUNDAY, Calendar.WEEKEND, 107 }, 108 }; 109 110 // We only test the getDayOfWeekType() and isWeekend() APIs. 111 // The getWeekendTransition() API is tested indirectly via the 112 // isWeekend() API, which calls it. 113 114 for (int i1=0; i1<DATA1.length; i1+=2) { 115 Locale loc = (Locale)DATA1[i1]; 116 int[] data = (int[]) DATA1[i1+1]; 117 Calendar cal = Calendar.getInstance(loc); 118 logln("Locale: " + loc); 119 for (int i=0; i<data.length; i+=6) { 120 cal.clear(); 121 cal.set(data[i], data[i+1], data[i+2], data[i+3], 0, 0); 122 if (data[i+4] != 0) { 123 cal.setTime(new Date(cal.getTime().getTime() + data[i+4])); 124 } 125 boolean isWeekend = cal.isWeekend(); 126 boolean ok = isWeekend == (data[i+5] != 0); 127 if (ok) { 128 logln("Ok: " + fmt.format(cal.getTime()) + " isWeekend=" + isWeekend); 129 } else { 130 errln("FAIL: " + fmt.format(cal.getTime()) + " isWeekend=" + isWeekend + 131 ", expected=" + (!isWeekend)); 132 } 133 } 134 } 135 136 for (int i2=0; i2<DATA2.length; i2+=2) { 137 Locale loc = (Locale)DATA2[i2]; 138 int[] data = (int[]) DATA2[i2+1]; 139 logln("Locale: " + loc); 140 Calendar cal = Calendar.getInstance(loc); 141 for (int i=0; i<data.length; i+=2) { 142 int type = cal.getDayOfWeekType(data[i]); 143 int exp = data[i+1]; 144 if (type == exp) { 145 logln("Ok: DOW " + data[i] + " type=" + type); 146 } else { 147 errln("FAIL: DOW " + data[i] + " type=" + type + 148 ", expected=" + exp); 149 } 150 } 151 } 152 } 153 154 /** 155 * Run a test of a quasi-Gregorian calendar. This is a calendar 156 * that behaves like a Gregorian but has different year/era mappings. 157 * The int[] data array should have the format: 158 * 159 * { era, year, gregorianYear, month, dayOfMonth, ... } 160 */ quasiGregorianTest(Calendar cal, int[] data)161 void quasiGregorianTest(Calendar cal, int[] data) { 162 // As of JDK 1.4.1_01, using the Sun JDK GregorianCalendar as 163 // a reference throws us off by one hour. This is most likely 164 // due to the JDK 1.4 incorporation of historical time zones. 165 //java.util.Calendar grego = java.util.Calendar.getInstance(); 166 Calendar grego = Calendar.getInstance(); 167 for (int i=0; i<data.length; ) { 168 int era = data[i++]; 169 int year = data[i++]; 170 int gregorianYear = data[i++]; 171 int month = data[i++]; 172 int dayOfMonth = data[i++]; 173 174 grego.clear(); 175 grego.set(gregorianYear, month, dayOfMonth); 176 Date D = grego.getTime(); 177 178 cal.clear(); 179 cal.set(Calendar.ERA, era); 180 cal.set(year, month, dayOfMonth); 181 Date d = cal.getTime(); 182 if (d.equals(D)) { 183 logln("OK: " + era + ":" + year + "/" + (month+1) + "/" + dayOfMonth + 184 " => " + d); 185 } else { 186 errln("Fail: " + era + ":" + year + "/" + (month+1) + "/" + dayOfMonth + 187 " => " + d + ", expected " + D); 188 } 189 190 cal.clear(); 191 cal.setTime(D); 192 int e = cal.get(Calendar.ERA); 193 int y = cal.get(Calendar.YEAR); 194 if (y == year && e == era) { 195 logln("OK: " + D + " => " + cal.get(Calendar.ERA) + ":" + 196 cal.get(Calendar.YEAR) + "/" + 197 (cal.get(Calendar.MONTH)+1) + "/" + cal.get(Calendar.DATE)); 198 } else { 199 logln("Fail: " + D + " => " + cal.get(Calendar.ERA) + ":" + 200 cal.get(Calendar.YEAR) + "/" + 201 (cal.get(Calendar.MONTH)+1) + "/" + cal.get(Calendar.DATE) + 202 ", expected " + era + ":" + year + "/" + (month+1) + "/" + 203 dayOfMonth); 204 } 205 } 206 } 207 208 /** 209 * Verify that BuddhistCalendar shifts years to Buddhist Era but otherwise 210 * behaves like GregorianCalendar. 211 */ 212 @Test TestBuddhist()213 public void TestBuddhist() { 214 quasiGregorianTest(new BuddhistCalendar(), 215 new int[] { 216 // BE 2542 == 1999 CE 217 0, 2542, 1999, Calendar.JUNE, 4 218 }); 219 } 220 221 @Test TestBuddhistCoverage()222 public void TestBuddhistCoverage() { 223 { 224 // new BuddhistCalendar(ULocale) 225 BuddhistCalendar cal = new BuddhistCalendar(ULocale.getDefault()); 226 if(cal == null){ 227 errln("could not create BuddhistCalendar with ULocale"); 228 } 229 } 230 231 { 232 // new BuddhistCalendar(TimeZone,ULocale) 233 BuddhistCalendar cal = new BuddhistCalendar(TimeZone.getDefault(),ULocale.getDefault()); 234 if(cal == null){ 235 errln("could not create BuddhistCalendar with TimeZone ULocale"); 236 } 237 } 238 239 { 240 // new BuddhistCalendar(TimeZone) 241 BuddhistCalendar cal = new BuddhistCalendar(TimeZone.getDefault()); 242 if(cal == null){ 243 errln("could not create BuddhistCalendar with TimeZone"); 244 } 245 } 246 247 { 248 // new BuddhistCalendar(Locale) 249 BuddhistCalendar cal = new BuddhistCalendar(Locale.getDefault()); 250 if(cal == null){ 251 errln("could not create BuddhistCalendar with Locale"); 252 } 253 } 254 255 { 256 // new BuddhistCalendar(TimeZone, Locale) 257 BuddhistCalendar cal = new BuddhistCalendar(TimeZone.getDefault(), Locale.getDefault()); 258 if(cal == null){ 259 errln("could not create BuddhistCalendar with TimeZone and Locale"); 260 } 261 } 262 263 { 264 // new BuddhistCalendar(Date) 265 BuddhistCalendar cal = new BuddhistCalendar(new Date()); 266 if(cal == null){ 267 errln("could not create BuddhistCalendar with Date"); 268 } 269 } 270 271 { 272 // new BuddhistCalendar(int year, int month, int date) 273 BuddhistCalendar cal = new BuddhistCalendar(2543, Calendar.MAY, 22); 274 if(cal == null){ 275 errln("could not create BuddhistCalendar with year,month,data"); 276 } 277 } 278 279 { 280 // new BuddhistCalendar(int year, int month, int date, int hour, int minute, int second) 281 BuddhistCalendar cal = new BuddhistCalendar(2543, Calendar.MAY, 22, 1, 1, 1); 282 if(cal == null){ 283 errln("could not create BuddhistCalendar with year,month,date,hour,minute,second"); 284 } 285 } 286 287 { 288 // data 289 BuddhistCalendar cal = new BuddhistCalendar(2543, Calendar.MAY, 22); 290 Date time = cal.getTime(); 291 292 String[] calendarLocales = { 293 "th_TH" 294 }; 295 296 String[] formatLocales = { 297 "en", "ar", "hu", "th" 298 }; 299 300 for (int i = 0; i < calendarLocales.length; ++i) { 301 String calLocName = calendarLocales[i]; 302 Locale calLocale = LocaleUtility.getLocaleFromName(calLocName); 303 cal = new BuddhistCalendar(calLocale); 304 305 for (int j = 0; j < formatLocales.length; ++j) { 306 String locName = formatLocales[j]; 307 Locale formatLocale = LocaleUtility.getLocaleFromName(locName); 308 DateFormat format = DateFormat.getDateTimeInstance(cal, DateFormat.FULL, DateFormat.FULL, formatLocale); 309 logln(calLocName + "/" + locName + " --> " + format.format(time)); 310 } 311 } 312 } 313 } 314 315 /** 316 * Test limits of the Buddhist calendar. 317 */ 318 @Test TestBuddhistLimits()319 public void TestBuddhistLimits() { 320 // Final parameter is either number of days, if > 0, or test 321 // duration in seconds, if < 0. 322 Calendar cal = Calendar.getInstance(); 323 cal.set(2007, Calendar.JANUARY, 1); 324 BuddhistCalendar buddhist = new BuddhistCalendar(); 325 doLimitsTest(buddhist, null, cal.getTime()); 326 doTheoreticalLimitsTest(buddhist, false); 327 } 328 329 /** 330 * Default calendar for Thai (Ticket#6302) 331 */ 332 @Test TestThaiDefault()333 public void TestThaiDefault() { 334 // Buddhist calendar is used as the default calendar for 335 // Thai locale 336 Calendar cal = Calendar.getInstance(new ULocale("th_TH")); 337 String type = cal.getType(); 338 if (!type.equals("gregorian")) { 339 errln("FAIL: Gregorian calendar is not returned for locale " + cal.toString()); 340 } 341 } 342 343 /** 344 * Verify that TaiwanCalendar shifts years to Minguo Era but otherwise 345 * behaves like GregorianCalendar. 346 */ 347 @Test TestTaiwan()348 public void TestTaiwan() { 349 quasiGregorianTest(new TaiwanCalendar(), 350 new int[] { 351 TaiwanCalendar.BEFORE_MINGUO, 8, 1904, Calendar.FEBRUARY, 29, 352 TaiwanCalendar.MINGUO, 1, 1912, Calendar.JUNE, 4, 353 TaiwanCalendar.MINGUO, 3, 1914, Calendar.FEBRUARY, 12, 354 TaiwanCalendar.MINGUO, 96,2007, Calendar.FEBRUARY, 12, 355 }); 356 } 357 358 /** 359 * Test limits of the Taiwan calendar. 360 */ 361 @Test TestTaiwanLimits()362 public void TestTaiwanLimits() { 363 // Final parameter is either number of days, if > 0, or test 364 // duration in seconds, if < 0. 365 Calendar cal = Calendar.getInstance(); 366 cal.set(2007, Calendar.JANUARY, 1); 367 TaiwanCalendar taiwan = new TaiwanCalendar(); 368 doLimitsTest(taiwan, null, cal.getTime()); 369 doTheoreticalLimitsTest(taiwan, false); 370 } 371 372 @Test TestTaiwanCoverage()373 public void TestTaiwanCoverage() { 374 { 375 // new TaiwanCalendar(ULocale) 376 TaiwanCalendar cal = new TaiwanCalendar(ULocale.getDefault()); 377 if(cal == null){ 378 errln("could not create TaiwanCalendar with ULocale"); 379 } 380 } 381 382 { 383 // new TaiwanCalendar(TimeZone,ULocale) 384 TaiwanCalendar cal = new TaiwanCalendar(TimeZone.getDefault(),ULocale.getDefault()); 385 if(cal == null){ 386 errln("could not create TaiwanCalendar with TimeZone ULocale"); 387 } 388 } 389 390 { 391 // new TaiwanCalendar(TimeZone) 392 TaiwanCalendar cal = new TaiwanCalendar(TimeZone.getDefault()); 393 if(cal == null){ 394 errln("could not create TaiwanCalendar with TimeZone"); 395 } 396 } 397 398 { 399 // new TaiwanCalendar(Locale) 400 TaiwanCalendar cal = new TaiwanCalendar(Locale.getDefault()); 401 if(cal == null){ 402 errln("could not create TaiwanCalendar with Locale"); 403 } 404 } 405 406 { 407 // new TaiwanCalendar(TimeZone, Locale) 408 TaiwanCalendar cal = new TaiwanCalendar(TimeZone.getDefault(), Locale.getDefault()); 409 if(cal == null){ 410 errln("could not create TaiwanCalendar with TimeZone and Locale"); 411 } 412 } 413 414 { 415 // new TaiwanCalendar(Date) 416 TaiwanCalendar cal = new TaiwanCalendar(new Date()); 417 if(cal == null){ 418 errln("could not create TaiwanCalendar with Date"); 419 } 420 } 421 422 { 423 // new TaiwanCalendar(int year, int month, int date) 424 TaiwanCalendar cal = new TaiwanCalendar(34, Calendar.MAY, 22); 425 if(cal == null){ 426 errln("could not create TaiwanCalendar with year,month,data"); 427 } 428 } 429 430 { 431 // new TaiwanCalendar(int year, int month, int date, int hour, int minute, int second) 432 TaiwanCalendar cal = new TaiwanCalendar(34, Calendar.MAY, 22, 1, 1, 1); 433 if(cal == null){ 434 errln("could not create TaiwanCalendar with year,month,date,hour,minute,second"); 435 } 436 } 437 438 { 439 // data 440 TaiwanCalendar cal = new TaiwanCalendar(34, Calendar.MAY, 22); 441 Date time = cal.getTime(); 442 443 String[] calendarLocales = { 444 "en","zh" 445 }; 446 447 String[] formatLocales = { 448 "en", "ar", "hu", "th" 449 }; 450 451 for (int i = 0; i < calendarLocales.length; ++i) { 452 String calLocName = calendarLocales[i]; 453 Locale calLocale = LocaleUtility.getLocaleFromName(calLocName); 454 cal = new TaiwanCalendar(calLocale); 455 456 for (int j = 0; j < formatLocales.length; ++j) { 457 String locName = formatLocales[j]; 458 Locale formatLocale = LocaleUtility.getLocaleFromName(locName); 459 DateFormat format = DateFormat.getDateTimeInstance(cal, DateFormat.FULL, DateFormat.FULL, formatLocale); 460 logln(calLocName + "/" + locName + " --> " + format.format(time)); 461 } 462 } 463 } 464 } 465 466 /** 467 * Verify that JapaneseCalendar shifts years to Japanese Eras but otherwise 468 * behaves like GregorianCalendar. 469 */ 470 @Test TestJapanese()471 public void TestJapanese() { 472 // First make sure this test works for GregorianCalendar 473 int[] control = { 474 GregorianCalendar.AD, 1868, 1868, Calendar.SEPTEMBER, 8, 475 GregorianCalendar.AD, 1868, 1868, Calendar.SEPTEMBER, 9, 476 GregorianCalendar.AD, 1869, 1869, Calendar.JUNE, 4, 477 GregorianCalendar.AD, 1912, 1912, Calendar.JULY, 29, 478 GregorianCalendar.AD, 1912, 1912, Calendar.JULY, 30, 479 GregorianCalendar.AD, 1912, 1912, Calendar.AUGUST, 1, 480 }; 481 quasiGregorianTest(new GregorianCalendar(), control); 482 483 int[] data = { 484 JapaneseCalendar.MEIJI, 1, 1868, Calendar.SEPTEMBER, 8, 485 JapaneseCalendar.MEIJI, 1, 1868, Calendar.SEPTEMBER, 9, 486 JapaneseCalendar.MEIJI, 2, 1869, Calendar.JUNE, 4, 487 JapaneseCalendar.MEIJI, 45, 1912, Calendar.JULY, 29, 488 JapaneseCalendar.TAISHO, 1, 1912, Calendar.JULY, 30, 489 JapaneseCalendar.TAISHO, 1, 1912, Calendar.AUGUST, 1, 490 }; 491 quasiGregorianTest(new JapaneseCalendar(), data); 492 } 493 494 /** 495 * Test limits of the Gregorian calendar. 496 */ 497 @Test TestGregorianLimits()498 public void TestGregorianLimits() { 499 // Final parameter is either number of days, if > 0, or test 500 // duration in seconds, if < 0. 501 Calendar cal = Calendar.getInstance(); 502 cal.set(2004, Calendar.JANUARY, 1); 503 GregorianCalendar gregorian = new GregorianCalendar(); 504 doLimitsTest(gregorian, null, cal.getTime()); 505 doTheoreticalLimitsTest(gregorian, false); 506 } 507 508 /** 509 * Test behavior of fieldDifference around leap years. Also test a large 510 * field difference to check binary search. 511 */ 512 @Test TestLeapFieldDifference()513 public void TestLeapFieldDifference() { 514 Calendar cal = Calendar.getInstance(); 515 cal.set(2004, Calendar.FEBRUARY, 29); 516 Date date2004 = cal.getTime(); 517 cal.set(2000, Calendar.FEBRUARY, 29); 518 Date date2000 = cal.getTime(); 519 int y = cal.fieldDifference(date2004, Calendar.YEAR); 520 int d = cal.fieldDifference(date2004, Calendar.DAY_OF_YEAR); 521 if (d == 0) { 522 logln("Ok: 2004/Feb/29 - 2000/Feb/29 = " + y + " years, " + d + " days"); 523 } else { 524 errln("FAIL: 2004/Feb/29 - 2000/Feb/29 = " + y + " years, " + d + " days"); 525 } 526 cal.setTime(date2004); 527 y = cal.fieldDifference(date2000, Calendar.YEAR); 528 d = cal.fieldDifference(date2000, Calendar.DAY_OF_YEAR); 529 if (d == 0) { 530 logln("Ok: 2000/Feb/29 - 2004/Feb/29 = " + y + " years, " + d + " days"); 531 } else { 532 errln("FAIL: 2000/Feb/29 - 2004/Feb/29 = " + y + " years, " + d + " days"); 533 } 534 // Test large difference 535 cal.set(2001, Calendar.APRIL, 5); // 2452005 536 Date ayl = cal.getTime(); 537 cal.set(1964, Calendar.SEPTEMBER, 7); // 2438646 538 Date asl = cal.getTime(); 539 d = cal.fieldDifference(ayl, Calendar.DAY_OF_MONTH); 540 cal.setTime(ayl); 541 int d2 = cal.fieldDifference(asl, Calendar.DAY_OF_MONTH); 542 if (d == -d2 && d == 13359) { 543 logln("Ok: large field difference symmetrical " + d); 544 } else { 545 logln("FAIL: large field difference incorrect " + d + ", " + d2 + 546 ", expect +/- 13359"); 547 } 548 } 549 550 /** 551 * Test ms_MY "Malay (Malaysia)" locale. Bug 1543. 552 */ 553 @Test TestMalaysianInstance()554 public void TestMalaysianInstance() { 555 Locale loc = new Locale("ms", "MY"); // Malay (Malaysia) 556 Calendar cal = Calendar.getInstance(loc); 557 if(cal == null){ 558 errln("could not create Malaysian instance"); 559 } 560 } 561 562 /** 563 * setFirstDayOfWeek and setMinimalDaysInFirstWeek may change the 564 * field <=> time mapping, since they affect the interpretation of 565 * the WEEK_OF_MONTH or WEEK_OF_YEAR fields. 566 */ 567 @Test TestWeekShift()568 public void TestWeekShift() { 569 Calendar cal = new GregorianCalendar( 570 TimeZone.getTimeZone("America/Los_Angeles"), 571 new Locale("en", "US")); 572 cal.setTime(new Date(997257600000L)); // Wed Aug 08 01:00:00 PDT 2001 573 // In pass one, change the first day of week so that the weeks 574 // shift in August 2001. In pass two, change the minimal days 575 // in the first week so that the weeks shift in August 2001. 576 // August 2001 577 // Su Mo Tu We Th Fr Sa 578 // 1 2 3 4 579 // 5 6 7 8 9 10 11 580 // 12 13 14 15 16 17 18 581 // 19 20 21 22 23 24 25 582 // 26 27 28 29 30 31 583 for (int pass=0; pass<2; ++pass) { 584 if (pass==0) { 585 cal.setFirstDayOfWeek(Calendar.WEDNESDAY); 586 cal.setMinimalDaysInFirstWeek(4); 587 } else { 588 cal.setFirstDayOfWeek(Calendar.SUNDAY); 589 cal.setMinimalDaysInFirstWeek(4); 590 } 591 cal.add(Calendar.DATE, 1); // Force recalc 592 cal.add(Calendar.DATE, -1); 593 594 Date time1 = cal.getTime(); // Get time -- should not change 595 596 // Now change a week parameter and then force a recalc. 597 // The bug is that the recalc should not be necessary -- 598 // calendar should do so automatically. 599 if (pass==0) { 600 cal.setFirstDayOfWeek(Calendar.THURSDAY); 601 } else { 602 cal.setMinimalDaysInFirstWeek(5); 603 } 604 605 int woy1 = cal.get(Calendar.WEEK_OF_YEAR); 606 int wom1 = cal.get(Calendar.WEEK_OF_MONTH); 607 608 cal.add(Calendar.DATE, 1); // Force recalc 609 cal.add(Calendar.DATE, -1); 610 611 int woy2 = cal.get(Calendar.WEEK_OF_YEAR); 612 int wom2 = cal.get(Calendar.WEEK_OF_MONTH); 613 614 Date time2 = cal.getTime(); 615 616 if (!time1.equals(time2)) { 617 errln("FAIL: shifting week should not alter time"); 618 } else { 619 logln(time1.toString()); 620 } 621 if (woy1 == woy2 && wom1 == wom2) { 622 logln("Ok: WEEK_OF_YEAR: " + woy1 + 623 ", WEEK_OF_MONTH: " + wom1); 624 } else { 625 errln("FAIL: WEEK_OF_YEAR: " + woy1 + " => " + woy2 + 626 ", WEEK_OF_MONTH: " + wom1 + " => " + wom2 + 627 " after week shift"); 628 } 629 } 630 } 631 632 /** 633 * Make sure that when adding a day, we actually wind up in a 634 * different day. The DST adjustments we use to keep the hour 635 * constant across DST changes can backfire and change the day. 636 */ 637 @Test TestTimeZoneTransitionAdd()638 public void TestTimeZoneTransitionAdd() { 639 Locale locale = Locale.US; // could also be CHINA 640 SimpleDateFormat dateFormat = 641 new SimpleDateFormat("MM/dd/yyyy HH:mm z", locale); 642 643 String tz[] = TimeZone.getAvailableIDs(); 644 645 for (int z=0; z<tz.length; ++z) { 646 TimeZone t = TimeZone.getTimeZone(tz[z]); 647 dateFormat.setTimeZone(t); 648 649 Calendar cal = Calendar.getInstance(t, locale); 650 cal.clear(); 651 // Scan the year 2003, overlapping the edges of the year 652 cal.set(Calendar.YEAR, 2002); 653 cal.set(Calendar.MONTH, Calendar.DECEMBER); 654 cal.set(Calendar.DAY_OF_MONTH, 25); 655 656 for (int i=0; i<365+10; ++i) { 657 Date yesterday = cal.getTime(); 658 int yesterday_day = cal.get(Calendar.DAY_OF_MONTH); 659 cal.add(Calendar.DAY_OF_MONTH, 1); 660 if (yesterday_day == cal.get(Calendar.DAY_OF_MONTH)) { 661 errln(tz[z] + " " + 662 dateFormat.format(yesterday) + " +1d= " + 663 dateFormat.format(cal.getTime())); 664 } 665 } 666 } 667 } 668 669 @Test TestJB1684()670 public void TestJB1684() { 671 class TestData { 672 int year; 673 int month; 674 int date; 675 int womyear; 676 int wommon; 677 int wom; 678 int dow; 679 String data; 680 String normalized; 681 682 public TestData(int year, int month, int date, 683 int womyear, int wommon, int wom, int dow, 684 String data, String normalized) { 685 this.year = year; 686 this.month = month-1; 687 this.date = date; 688 this.womyear = womyear; 689 this.wommon = wommon-1; 690 this.wom = wom; 691 this.dow = dow; 692 this.data = data; // year, month, week of month, day 693 this.normalized = data; 694 if (normalized != null) this.normalized = normalized; 695 } 696 } 697 698 // July 2001 August 2001 January 2002 699 // Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa 700 // 1 2 3 4 5 6 7 1 2 3 4 1 2 3 4 5 701 // 8 9 10 11 12 13 14 5 6 7 8 9 10 11 6 7 8 9 10 11 12 702 // 15 16 17 18 19 20 21 12 13 14 15 16 17 18 13 14 15 16 17 18 19 703 // 22 23 24 25 26 27 28 19 20 21 22 23 24 25 20 21 22 23 24 25 26 704 // 29 30 31 26 27 28 29 30 31 27 28 29 30 31 705 TestData[] tests = { 706 new TestData(2001, 8, 6, 2001,8,2,Calendar.MONDAY, "2001 08 02 Mon", null), 707 new TestData(2001, 8, 7, 2001,8,2,Calendar.TUESDAY, "2001 08 02 Tue", null), 708 new TestData(2001, 8, 5,/*12,*/ 2001,8,2,Calendar.SUNDAY, "2001 08 02 Sun", null), 709 new TestData(2001, 8,6, /*7, 30,*/ 2001,7,6,Calendar.MONDAY, "2001 07 06 Mon", "2001 08 02 Mon"), 710 new TestData(2001, 8,7, /*7, 31,*/ 2001,7,6,Calendar.TUESDAY, "2001 07 06 Tue", "2001 08 02 Tue"), 711 new TestData(2001, 8, 5, 2001,7,6,Calendar.SUNDAY, "2001 07 06 Sun", "2001 08 02 Sun"), 712 new TestData(2001, 7, 30, 2001,8,1,Calendar.MONDAY, "2001 08 01 Mon", "2001 07 05 Mon"), 713 new TestData(2001, 7, 31, 2001,8,1,Calendar.TUESDAY, "2001 08 01 Tue", "2001 07 05 Tue"), 714 new TestData(2001, 7,29, /*8, 5,*/ 2001,8,1,Calendar.SUNDAY, "2001 08 01 Sun", "2001 07 05 Sun"), 715 new TestData(2001, 12, 31, 2001,12,6,Calendar.MONDAY, "2001 12 06 Mon", null), 716 new TestData(2002, 1, 1, 2002,1,1,Calendar.TUESDAY, "2002 01 01 Tue", null), 717 new TestData(2002, 1, 2, 2002,1,1,Calendar.WEDNESDAY, "2002 01 01 Wed", null), 718 new TestData(2002, 1, 3, 2002,1,1,Calendar.THURSDAY, "2002 01 01 Thu", null), 719 new TestData(2002, 1, 4, 2002,1,1,Calendar.FRIDAY, "2002 01 01 Fri", null), 720 new TestData(2002, 1, 5, 2002,1,1,Calendar.SATURDAY, "2002 01 01 Sat", null), 721 new TestData(2001,12,30, /*2002, 1, 6,*/ 2002,1,1,Calendar.SUNDAY, "2002 01 01 Sun", "2001 12 06 Sun"), 722 }; 723 724 int pass = 0, error = 0, warning = 0; 725 726 final String pattern = "yyyy MM WW EEE"; 727 GregorianCalendar cal = new GregorianCalendar(); 728 SimpleDateFormat sdf = new SimpleDateFormat(pattern); 729 sdf.setCalendar(cal); 730 731 cal.setFirstDayOfWeek(Calendar.SUNDAY); 732 cal.setMinimalDaysInFirstWeek(1); 733 734 for (int i = 0; i < tests.length; ++i) { 735 TestData test = tests[i]; 736 log("\n-----\nTesting round trip of " + test.year + 737 " " + (test.month + 1) + 738 " " + test.date + 739 " (written as) " + test.data); 740 741 cal.clear(); 742 cal.set(test.year, test.month, test.date); 743 Date ms = cal.getTime(); 744 745 cal.clear(); 746 cal.set(Calendar.YEAR, test.womyear); 747 cal.set(Calendar.MONTH, test.wommon); 748 cal.set(Calendar.WEEK_OF_MONTH, test.wom); 749 cal.set(Calendar.DAY_OF_WEEK, test.dow); 750 Date ms2 = cal.getTime(); 751 752 if (!ms2.equals(ms)) { 753 log("\nError: GregorianCalendar.DOM gave " + ms + 754 "\n GregorianCalendar.WOM gave " + ms2); 755 error++; 756 } else { 757 pass++; 758 } 759 760 ms2 = null; 761 try { 762 ms2 = sdf.parse(test.data); 763 } 764 catch (ParseException e) { 765 errln("parse exception: " + e); 766 } 767 768 if (!ms2.equals(ms)) { 769 log("\nError: GregorianCalendar gave " + ms + 770 "\n SimpleDateFormat.parse gave " + ms2); 771 error++; 772 } else { 773 pass++; 774 } 775 776 String result = sdf.format(ms); 777 if (!result.equals(test.normalized)) { 778 log("\nWarning: format of '" + test.data + "' gave" + 779 "\n '" + result + "'" + 780 "\n expected '" + test.normalized + "'"); 781 warning++; 782 } else { 783 pass++; 784 } 785 786 Date ms3 = null; 787 try { 788 ms3 = sdf.parse(result); 789 } 790 catch (ParseException e) { 791 errln("parse exception 2: " + e); 792 } 793 794 if (!ms3.equals(ms)) { 795 error++; 796 log("\nError: Re-parse of '" + result + "' gave time of " + 797 "\n " + ms3 + 798 "\n not " + ms); 799 } else { 800 pass++; 801 } 802 } 803 String info = "\nPassed: " + pass + ", Warnings: " + warning + ", Errors: " + error; 804 if (error > 0) { 805 errln(info); 806 } else { 807 logln(info); 808 } 809 } 810 811 /** 812 * Test the ZoneMeta API. 813 */ 814 @Test TestZoneMeta()815 public void TestZoneMeta() { 816 // Test index by country API 817 818 // Format: {country, zone1, zone2, ..., zoneN} 819 String COUNTRY[][] = { {""}, 820 {"US", "America/Los_Angeles", "PST"} }; 821 StringBuffer buf = new StringBuffer(); 822 for (int i=0; i<COUNTRY.length; ++i) { 823 Set<String> a = ZoneMeta.getAvailableIDs(SystemTimeZoneType.ANY, COUNTRY[i][0], null); 824 buf.setLength(0); 825 buf.append("Country \"" + COUNTRY[i][0] + "\": ["); 826 // Use bitmask to track which of the expected zones we see 827 int mask = 0; 828 boolean first = true; 829 for (String z : a) { 830 if (first) { 831 first = false; 832 } else { 833 buf.append(", "); 834 } 835 buf.append(z); 836 for (int k = 1; k < COUNTRY[i].length; ++k) { 837 if ((mask & (1 << k)) == 0 && z.equals(COUNTRY[i][k])) { 838 mask |= (1 << k); 839 } 840 } 841 } 842 buf.append("]"); 843 mask >>= 1; 844 // Check bitmask to see if we saw all expected zones 845 if (mask == (1 << (COUNTRY[i].length-1))-1) { 846 logln(buf.toString()); 847 } else { 848 errln(buf.toString()); 849 } 850 } 851 852 // Test equivalent IDs API 853 854 int n = ZoneMeta.countEquivalentIDs("PST"); 855 boolean ok = false; 856 buf.setLength(0); 857 buf.append("Equivalent to PST: "); 858 for (int i=0; i<n; ++i) { 859 String id = ZoneMeta.getEquivalentID("PST", i); 860 if (id.equals("America/Los_Angeles")) { 861 ok = true; 862 } 863 if (i!=0) buf.append(", "); 864 buf.append(id); 865 } 866 if (ok) { 867 logln(buf.toString()); 868 } else { 869 errln(buf.toString()); 870 } 871 } 872 873 @Test TestComparable()874 public void TestComparable() { 875 GregorianCalendar c0 = new GregorianCalendar(); 876 GregorianCalendar c1 = new GregorianCalendar(); 877 c1.add(Calendar.DAY_OF_MONTH, 1); 878 if (c0.compareTo(c1) >= 0) { 879 errln("calendar " + c0 + " not < " + c1); 880 } 881 c0.add(Calendar.MONTH, 1); 882 if (c0.compareTo(c1) <= 0) { 883 errln("calendar " + c0 + " not > " + c1); 884 } 885 886 c0.setTimeInMillis(c1.getTimeInMillis()); 887 if (c0.compareTo(c1) != 0) { 888 errln("calendar " + c0 + " not == " + c1); 889 } 890 891 } 892 893 /** 894 * Miscellaneous tests to increase coverage. 895 */ 896 @Test TestCoverage()897 public void TestCoverage() { 898 // BuddhistCalendar 899 BuddhistCalendar bcal = new BuddhistCalendar(); 900 /*int i =*/ bcal.getMinimum(Calendar.ERA); 901 bcal.add(Calendar.YEAR, 1); 902 bcal.add(Calendar.MONTH, 1); 903 /*Date d = */bcal.getTime(); 904 905 // CalendarAstronomer 906 // (This class should probably be made package-private.) 907 CalendarAstronomer astro = new CalendarAstronomer(); 908 /*String s = */astro.local(0); 909 910 // ChineseCalendar 911 ChineseCalendar ccal = new ChineseCalendar(TimeZone.getDefault(), 912 Locale.getDefault()); 913 ccal.add(Calendar.MONTH, 1); 914 ccal.add(Calendar.YEAR, 1); 915 ccal.roll(Calendar.MONTH, 1); 916 ccal.roll(Calendar.YEAR, 1); 917 ccal.getTime(); 918 919 // ICU 2.6 920 Calendar cal = Calendar.getInstance(Locale.US); 921 logln(cal.toString()); 922 logln(cal.getDisplayName(Locale.US)); 923 int weekendOnset=-1; 924 int weekendCease=-1; 925 for (int i=Calendar.SUNDAY; i<=Calendar.SATURDAY; ++i) { 926 if (cal.getDayOfWeekType(i) == Calendar.WEEKEND_ONSET) { 927 weekendOnset = i; 928 } 929 if (cal.getDayOfWeekType(i) == Calendar.WEEKEND_CEASE) { 930 weekendCease = i; 931 } 932 } 933 // can't call this unless we get a transition day (unusual), 934 // but make the call anyway for coverage reasons 935 try { 936 /*int x=*/ cal.getWeekendTransition(weekendOnset); 937 /*int x=*/ cal.getWeekendTransition(weekendCease); 938 } catch (IllegalArgumentException e) {} 939 /*int x=*/ cal.isWeekend(new Date()); 940 941 // new GregorianCalendar(ULocale) 942 GregorianCalendar gcal = new GregorianCalendar(ULocale.getDefault()); 943 if(gcal==null){ 944 errln("could not create GregorianCalendar with ULocale"); 945 } else { 946 logln("Calendar display name: " + gcal.getDisplayName(ULocale.getDefault())); 947 } 948 949 //cover getAvailableULocales 950 final ULocale[] locales = Calendar.getAvailableULocales(); 951 long count = locales.length; 952 if (count == 0) 953 errln("getAvailableULocales return empty list"); 954 logln("" + count + " available ulocales in Calendar."); 955 956 // Jitterbug 4451, for coverage 957 class StubCalendar extends Calendar{ 958 /** 959 * For serialization 960 */ 961 private static final long serialVersionUID = -4558903444622684759L; 962 963 @Override 964 protected int handleGetLimit(int field, int limitType) { 965 if (limitType == Calendar.LEAST_MAXIMUM) { 966 return 1; 967 } else if (limitType == Calendar.GREATEST_MINIMUM) { 968 return 7; 969 } 970 return -1; 971 } 972 @Override 973 protected int handleComputeMonthStart(int eyear, int month, boolean useMonth) { 974 if (useMonth) { 975 return eyear * 365 + month * 31; 976 } else { 977 return eyear * 365; 978 } 979 } 980 @Override 981 protected int handleGetExtendedYear() {return 2017;} 982 983 public void run(){ 984 if (Calendar.gregorianPreviousMonthLength(2000,2) != 29){ 985 errln("Year 2000 Feb should have 29 days."); 986 } 987 long millis = Calendar.julianDayToMillis(Calendar.MAX_JULIAN); 988 if(millis != Calendar.MAX_MILLIS){ 989 errln("Did not get the expected value from julianDayToMillis. Got:" + millis); 990 } 991 DateFormat df = handleGetDateFormat("",Locale.getDefault()); 992 if (!df.equals(handleGetDateFormat("",ULocale.getDefault()))){ 993 errln ("Calendar.handleGetDateFormat(String, Locale) should delegate to ( ,ULocale)"); 994 } 995 if (!getType().equals("unknown")){ 996 errln ("Calendar.getType() should be 'unknown'"); 997 } 998 999 // Tests for complete coverage of Calendar functions. 1000 int julianDay = Calendar.millisToJulianDay(millis - 1); 1001 assertEquals("Julian max day -1", julianDay, Calendar.MAX_JULIAN - 1); 1002 1003 DateFormat df1 = handleGetDateFormat("GG yyyy-d:MM", "option=xyz", Locale.getDefault()); 1004 if (!df1.equals(handleGetDateFormat("GG yyyy-d:MM", "option=xyz", ULocale.getDefault()))){ 1005 errln ("Calendar.handleGetDateFormat(String, Locale) should delegate to ( ,ULocale)"); 1006 } 1007 1008 // Prove that the local overrides are used. 1009 int leastMsInDay = handleGetLimit(Calendar.MILLISECONDS_IN_DAY, Calendar.LEAST_MAXIMUM); 1010 assertEquals("getLimit test 1", leastMsInDay, 1); 1011 int maxMsInDay = handleGetLimit(Calendar.WEEK_OF_MONTH, Calendar.GREATEST_MINIMUM); 1012 assertEquals("getLimit test 2", 7, maxMsInDay); 1013 1014 int febLeapLength = handleGetMonthLength(2020, Calendar.FEBRUARY); 1015 assertEquals("handleMonthLength", 31, febLeapLength); 1016 int exYear = handleGetExtendedYear(); 1017 assertEquals("handleGetExtendeYear", exYear, 2017); 1018 int monthStart = handleComputeMonthStart(2016, 4, false); 1019 assertEquals("handleComputeMonthStart false", 735840, monthStart); 1020 monthStart = handleComputeMonthStart(2016, 4, true); 1021 assertEquals("handleComputeMonthStart true", 735964, monthStart); 1022 1023 Calendar cal = Calendar.getInstance(); 1024 cal.set(1980, 5, 2); 1025 this.setTime(cal.getTime()); 1026 assertEquals("handleComputeFields: year set", 1980, get(YEAR)); 1027 assertEquals("handleComputeFields: month set", 5, get(MONTH)); 1028 assertEquals("handleComputeFields: day set", 2, get(DAY_OF_MONTH)); 1029 } 1030 } 1031 StubCalendar stub = new StubCalendar(); 1032 stub.run(); 1033 } 1034 1035 // Tests for jb 4541 1036 @Test TestJB4541()1037 public void TestJB4541() { 1038 ULocale loc = new ULocale("en_US"); 1039 1040 // !!! Shouldn't we have an api like this? 1041 // !!! Question: should this reflect those actually available in this copy of ICU, or 1042 // the list of types we assume is available? 1043 // String[] calTypes = Calendar.getAvailableTypes(); 1044 final String[] calTypes = { 1045 "buddhist", "chinese", "coptic", "ethiopic", "gregorian", "hebrew", 1046 "islamic", "islamic-civil", "japanese", "roc" 1047 }; 1048 1049 // constructing a DateFormat with a locale indicating a calendar type should construct a 1050 // date format appropriate to that calendar 1051 final Date time = new Date(); 1052 for (int i = 0; i < calTypes.length; ++i) { 1053 ULocale aLoc = loc.setKeywordValue("calendar", calTypes[i]); 1054 logln("locale: " + aLoc); 1055 1056 DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL, 1057 DateFormat.FULL, 1058 aLoc); 1059 1060 logln("df type: " + df.getClass().getName() + " loc: " + df.getLocale(ULocale.VALID_LOCALE)); 1061 1062 Calendar cal = df.getCalendar(); 1063 assertEquals("calendar types", cal.getType(), calTypes[i]); 1064 DateFormat df2 = cal.getDateTimeFormat(DateFormat.FULL, DateFormat.FULL, ULocale.US); 1065 logln("df2 type: " + df2.getClass().getName() + " loc: " + df2.getLocale(ULocale.VALID_LOCALE)); 1066 assertEquals("format results", df.format(time), df2.format(time)); 1067 } 1068 1069 // dateFormat.setCalendar should throw exception if wrong format for calendar 1070 if (false) { 1071 DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL, 1072 DateFormat.FULL, 1073 new ULocale("en_US@calendar=chinese")); 1074 1075 logln("dateformat type: " + df.getClass().getName()); 1076 1077 Calendar cal = Calendar.getInstance(new ULocale("en_US@calendar=chinese")); 1078 1079 logln("calendar type: " + cal.getClass().getName()); 1080 } 1081 } 1082 1083 @Test TestTypes()1084 public void TestTypes() { 1085 String[] locs = { 1086 "en_US_VALLEYGIRL", 1087 "en_US_VALLEYGIRL@collation=phonebook;calendar=japanese", 1088 "en_US_VALLEYGIRL@collation=phonebook;calendar=gregorian", 1089 "ja_JP@calendar=japanese", 1090 "th_TH@calendar=buddhist", 1091 "th-TH-u-ca-gregory", 1092 "th_TH_TRADITIONAL", 1093 "th_TH_TRADITIONAL@calendar=gregorian", 1094 "en_US", 1095 "th_TH", // Default calendar for th_TH is buddhist 1096 "th", // th's default region is TH and buddhist is used as default for TH 1097 "en_TH", // Default calendar for any locales with region TH is buddhist 1098 "th_TH@calendar=iso8601", // iso8601 calendar type 1099 "fr_CH", 1100 "fr_SA", 1101 "fr_CH@rg=sazzzz", 1102 "fr_CH@calendar=japanese;rg=sazzzz", 1103 "fr_TH@rg=SA", // ignore malformed rg tag, use buddhist 1104 "th@rg=SA", // ignore malformed rg tag, use buddhist 1105 }; 1106 1107 String[] types = { 1108 "gregorian", 1109 "japanese", 1110 "gregorian", 1111 "japanese", 1112 "buddhist", 1113 "gregorian", 1114 "gregorian", 1115 "gregorian", 1116 "gregorian", 1117 "gregorian", 1118 "gregorian", 1119 "gregorian", 1120 "gregorian", // iso8601 is a gregorian sub type 1121 "gregorian", 1122 "gregorian", 1123 "gregorian", 1124 "japanese", 1125 "gregorian", 1126 "gregorian", 1127 }; 1128 1129 for (int i = 0; i < locs.length; i++) { 1130 Calendar cal = Calendar.getInstance(new ULocale(locs[i])); 1131 if (!cal.getType().equals(types[i])) { 1132 errln(locs[i] + " Calendar type " + cal.getType() + " instead of " + types[i]); 1133 } 1134 } 1135 } 1136 1137 @Test TestISO8601()1138 public void TestISO8601() { 1139 final ULocale[] TEST_LOCALES = { 1140 new ULocale("en_US@calendar=iso8601"), 1141 new ULocale("en_US@calendar=Iso8601"), 1142 new ULocale("th_TH@calendar=iso8601"), 1143 new ULocale("ar_EG@calendar=iso8601") 1144 }; 1145 1146 final int[][] TEST_DATA = { 1147 // {<year>, <week# of Jan 1>, <week# year of Jan 1>} 1148 {2008, 1, 2008}, 1149 {2009, 1, 2009}, 1150 {2010, 53, 2009}, 1151 {2011, 52, 2010}, 1152 {2012, 52, 2011}, 1153 {2013, 1, 2013}, 1154 {2014, 1, 2014}, 1155 }; 1156 1157 for (ULocale locale : TEST_LOCALES) { 1158 Calendar cal = Calendar.getInstance(locale); 1159 // No matter what locale is used, if calendar type is "iso8601", 1160 // calendar type must be Gregorian 1161 if (!cal.getType().equals("gregorian")) { 1162 errln("Error: Gregorian calendar is not used for locale: " + locale); 1163 } 1164 1165 for (int[] data : TEST_DATA) { 1166 cal.set(data[0], Calendar.JANUARY, 1); 1167 int weekNum = cal.get(Calendar.WEEK_OF_YEAR); 1168 int weekYear = cal.get(Calendar.YEAR_WOY); 1169 1170 if (weekNum != data[1] || weekYear != data[2]) { 1171 errln("Error: Incorrect week of year on January 1st, " + data[0] 1172 + " for locale " + locale 1173 + ": Returned [weekNum=" + weekNum + ", weekYear=" + weekYear 1174 + "], Expected [weekNum=" + data[1] + ", weekYear=" + data[2] + "]"); 1175 } 1176 } 1177 } 1178 } 1179 1180 private static class CalFields { 1181 private int year; 1182 private int month; 1183 private int day; 1184 private int hour; 1185 private int min; 1186 private int sec; 1187 private int ms; 1188 CalFields(int year, int month, int day, int hour, int min, int sec)1189 CalFields(int year, int month, int day, int hour, int min, int sec) { 1190 this(year, month, day, hour, min, sec, 0); 1191 } 1192 CalFields(int year, int month, int day, int hour, int min, int sec, int ms)1193 CalFields(int year, int month, int day, int hour, int min, int sec, int ms) { 1194 this.year = year; 1195 this.month = month; 1196 this.day = day; 1197 this.hour = hour; 1198 this.min = min; 1199 this.sec = sec; 1200 this.ms = ms; 1201 } 1202 setTo(Calendar cal)1203 void setTo(Calendar cal) { 1204 cal.clear(); 1205 cal.set(year, month - 1, day, hour, min, sec); 1206 cal.set(Calendar.MILLISECOND, ms); 1207 } 1208 1209 @Override toString()1210 public String toString() { 1211 return String.format("%04d-%02d-%02d %02d:%02d:%02d.%03d", year, month, day, hour, min, sec, ms); 1212 } 1213 1214 @Override equals(Object other)1215 public boolean equals(Object other) { 1216 if (other instanceof CalFields) { 1217 CalFields otr = (CalFields)other; 1218 return (year == otr.year 1219 && month == otr.month 1220 && day == otr.day 1221 && hour == otr.hour 1222 && min == otr.min 1223 && sec == otr.sec 1224 && ms == otr.ms); 1225 } 1226 return false; 1227 } 1228 isEquivalentTo(Calendar cal)1229 boolean isEquivalentTo(Calendar cal) { 1230 return year == cal.get(Calendar.YEAR) 1231 && month == cal.get(Calendar.MONTH) + 1 1232 && day == cal.get(Calendar.DAY_OF_MONTH) 1233 && hour == cal.get(Calendar.HOUR_OF_DAY) 1234 && min == cal.get(Calendar.MINUTE) 1235 && sec == cal.get(Calendar.SECOND) 1236 && ms == cal.get(Calendar.MILLISECOND); 1237 } 1238 createFrom(Calendar cal)1239 static CalFields createFrom(Calendar cal) { 1240 int year = cal.get(Calendar.YEAR); 1241 int month = cal.get(Calendar.MONTH) + 1; 1242 int day = cal.get(Calendar.DAY_OF_MONTH); 1243 int hour = cal.get(Calendar.HOUR_OF_DAY); 1244 int min = cal.get(Calendar.MINUTE); 1245 int sec = cal.get(Calendar.SECOND); 1246 1247 return new CalFields(year, month, day, hour, min, sec); 1248 } 1249 } 1250 1251 @Test TestAmbiguousWallTimeAPIs()1252 public void TestAmbiguousWallTimeAPIs() { 1253 Calendar cal = Calendar.getInstance(); 1254 1255 assertEquals("Default repeated wall time option", cal.getRepeatedWallTimeOption(), Calendar.WALLTIME_LAST); 1256 assertEquals("Default skipped wall time option", cal.getSkippedWallTimeOption(), Calendar.WALLTIME_LAST); 1257 1258 Calendar cal2 = (Calendar)cal.clone(); 1259 1260 assertTrue("Equality", cal2.equals(cal)); 1261 assertTrue("Hash code", cal.hashCode() == cal2.hashCode()); 1262 1263 cal2.setRepeatedWallTimeOption(Calendar.WALLTIME_FIRST); 1264 cal2.setSkippedWallTimeOption(Calendar.WALLTIME_FIRST); 1265 1266 assertFalse("Equality after mod", cal2.equals(cal)); 1267 assertFalse("Hash code after mod", cal.hashCode() == cal2.hashCode()); 1268 1269 assertEquals("getRepeatedWallTimeOption after mod", cal2.getRepeatedWallTimeOption(), Calendar.WALLTIME_FIRST); 1270 assertEquals("getSkippedWallTimeOption after mod", cal2.getSkippedWallTimeOption(), Calendar.WALLTIME_FIRST); 1271 1272 try { 1273 cal.setRepeatedWallTimeOption(Calendar.WALLTIME_NEXT_VALID); 1274 errln("IAE expected on setRepeatedWallTimeOption(WALLTIME_NEXT_VALID"); 1275 } catch (IllegalArgumentException e) { 1276 // expected 1277 } 1278 } 1279 1280 @Test TestRepeatedWallTime()1281 public void TestRepeatedWallTime() { 1282 final Object[][] TESTDATA = { 1283 // Time zone Input wall time WALLTIME_LAST in GMT WALLTIME_FIRST in GMT 1284 {"America/New_York", new CalFields(2011,11,6,0,59,59), new CalFields(2011,11,6,4,59,59), new CalFields(2011,11,6,4,59,59)}, 1285 {"America/New_York", new CalFields(2011,11,6,1,0,0), new CalFields(2011,11,6,6,0,0), new CalFields(2011,11,6,5,0,0)}, 1286 {"America/New_York", new CalFields(2011,11,6,1,0,1), new CalFields(2011,11,6,6,0,1), new CalFields(2011,11,6,5,0,1)}, 1287 {"America/New_York", new CalFields(2011,11,6,1,30,0), new CalFields(2011,11,6,6,30,0), new CalFields(2011,11,6,5,30,0)}, 1288 {"America/New_York", new CalFields(2011,11,6,1,59,59), new CalFields(2011,11,6,6,59,59), new CalFields(2011,11,6,5,59,59)}, 1289 {"America/New_York", new CalFields(2011,11,6,2,0,0), new CalFields(2011,11,6,7,0,0), new CalFields(2011,11,6,7,0,0)}, 1290 {"America/New_York", new CalFields(2011,11,6,2,0,1), new CalFields(2011,11,6,7,0,1), new CalFields(2011,11,6,7,0,1)}, 1291 1292 {"Australia/Lord_Howe", new CalFields(2011,4,3,1,29,59), new CalFields(2011,4,2,14,29,59), new CalFields(2011,4,2,14,29,59)}, 1293 {"Australia/Lord_Howe", new CalFields(2011,4,3,1,30,0), new CalFields(2011,4,2,15,0,0), new CalFields(2011,4,2,14,30,0)}, 1294 {"Australia/Lord_Howe", new CalFields(2011,4,3,1,45,0), new CalFields(2011,4,2,15,15,0), new CalFields(2011,4,2,14,45,0)}, 1295 {"Australia/Lord_Howe", new CalFields(2011,4,3,1,59,59), new CalFields(2011,4,2,15,29,59), new CalFields(2011,4,2,14,59,59)}, 1296 {"Australia/Lord_Howe", new CalFields(2011,4,3,2,0,0), new CalFields(2011,4,2,15,30,0), new CalFields(2011,4,2,15,30,0)}, 1297 {"Australia/Lord_Howe", new CalFields(2011,4,3,2,0,1), new CalFields(2011,4,2,15,30,1), new CalFields(2011,4,2,15,30,1)}, 1298 }; 1299 1300 Calendar calGMT = Calendar.getInstance(TimeZone.GMT_ZONE); 1301 1302 Calendar calDefault = Calendar.getInstance(); 1303 Calendar calLast = Calendar.getInstance(); 1304 Calendar calFirst = Calendar.getInstance(); 1305 1306 calFirst.setRepeatedWallTimeOption(Calendar.WALLTIME_FIRST); 1307 calLast.setRepeatedWallTimeOption(Calendar.WALLTIME_LAST); 1308 1309 for (Object[] test : TESTDATA) { 1310 String tzid = (String)test[0]; 1311 TimeZone tz = TimeZone.getTimeZone(tzid); 1312 CalFields in = (CalFields)test[1]; 1313 CalFields expLastGMT = (CalFields)test[2]; 1314 CalFields expFirstGMT = (CalFields)test[3]; 1315 1316 // WALLTIME_LAST 1317 calLast.setTimeZone(tz); 1318 in.setTo(calLast); 1319 calGMT.setTimeInMillis(calLast.getTimeInMillis()); 1320 CalFields outLastGMT = CalFields.createFrom(calGMT); 1321 if (!outLastGMT.equals(expLastGMT)) { 1322 errln("Fail: WALLTIME_LAST " + in + "[" + tzid + "] is parsed as " + outLastGMT + "[GMT]. Expected: " + expLastGMT + "[GMT]"); 1323 } 1324 1325 // default 1326 calDefault.setTimeZone(tz); 1327 in.setTo(calDefault); 1328 calGMT.setTimeInMillis(calDefault.getTimeInMillis()); 1329 CalFields outDefGMT = CalFields.createFrom(calGMT); 1330 if (!outDefGMT.equals(expLastGMT)) { 1331 errln("Fail: (default) " + in + "[" + tzid + "] is parsed as " + outDefGMT + "[GMT]. Expected: " + expLastGMT + "[GMT]"); 1332 } 1333 1334 // WALLTIME_FIRST 1335 calFirst.setTimeZone(tz); 1336 in.setTo(calFirst); 1337 calGMT.setTimeInMillis(calFirst.getTimeInMillis()); 1338 CalFields outFirstGMT = CalFields.createFrom(calGMT); 1339 if (!outFirstGMT.equals(expFirstGMT)) { 1340 errln("Fail: WALLTIME_FIRST " + in + "[" + tzid + "] is parsed as " + outFirstGMT + "[GMT]. Expected: " + expFirstGMT + "[GMT]"); 1341 } 1342 } 1343 } 1344 1345 @Test TestSkippedWallTime()1346 public void TestSkippedWallTime() { 1347 final Object[][] TESTDATA = { 1348 // Time zone Input wall time Valid wall time? 1349 {"America/New_York", new CalFields(2011,3,13,1,59,59), true, 1350 // WALLTIME_LAST in GMT WALLTIME_FIRST in GMT WALLTIME_NEXT_VALID in GMT 1351 new CalFields(2011,3,13,6,59,59), new CalFields(2011,3,13,6,59,59), new CalFields(2011,3,13,6,59,59)}, 1352 1353 {"America/New_York", new CalFields(2011,3,13,2,0,0), false, 1354 new CalFields(2011,3,13,7,0,0), new CalFields(2011,3,13,6,0,0), new CalFields(2011,3,13,7,0,0)}, 1355 1356 {"America/New_York", new CalFields(2011,3,13,2,1,0), false, 1357 new CalFields(2011,3,13,7,1,0), new CalFields(2011,3,13,6,1,0), new CalFields(2011,3,13,7,0,0)}, 1358 1359 {"America/New_York", new CalFields(2011,3,13,2,30,0), false, 1360 new CalFields(2011,3,13,7,30,0), new CalFields(2011,3,13,6,30,0), new CalFields(2011,3,13,7,0,0)}, 1361 1362 {"America/New_York", new CalFields(2011,3,13,2,59,59), false, 1363 new CalFields(2011,3,13,7,59,59), new CalFields(2011,3,13,6,59,59), new CalFields(2011,3,13,7,0,0)}, 1364 1365 {"America/New_York", new CalFields(2011,3,13,3,0,0), true, 1366 new CalFields(2011,3,13,7,0,0), new CalFields(2011,3,13,7,0,0), new CalFields(2011,3,13,7,0,0)}, 1367 1368 {"Pacific/Apia", new CalFields(2011,12,29,23,59,59), true, 1369 new CalFields(2011,12,30,9,59,59), new CalFields(2011,12,30,9,59,59), new CalFields(2011,12,30,9,59,59)}, 1370 1371 {"Pacific/Apia", new CalFields(2011,12,30,0,0,0), false, 1372 new CalFields(2011,12,30,10,0,0), new CalFields(2011,12,29,10,0,0), new CalFields(2011,12,30,10,0,0)}, 1373 1374 {"Pacific/Apia", new CalFields(2011,12,30,12,0,0), false, 1375 new CalFields(2011,12,30,22,0,0), new CalFields(2011,12,29,22,0,0), new CalFields(2011,12,30,10,0,0)}, 1376 1377 {"Pacific/Apia", new CalFields(2011,12,30,23,59,59), false, 1378 new CalFields(2011,12,31,9,59,59), new CalFields(2011,12,30,9,59,59), new CalFields(2011,12,30,10,0,0)}, 1379 1380 {"Pacific/Apia", new CalFields(2011,12,31,0,0,0), true, 1381 new CalFields(2011,12,30,10,0,0), new CalFields(2011,12,30,10,0,0), new CalFields(2011,12,30,10,0,0)}, 1382 }; 1383 1384 Calendar calGMT = Calendar.getInstance(TimeZone.GMT_ZONE); 1385 1386 Calendar calDefault = Calendar.getInstance(); 1387 Calendar calLast = Calendar.getInstance(); 1388 Calendar calFirst = Calendar.getInstance(); 1389 Calendar calNextAvail = Calendar.getInstance(); 1390 1391 calLast.setSkippedWallTimeOption(Calendar.WALLTIME_LAST); 1392 calFirst.setSkippedWallTimeOption(Calendar.WALLTIME_FIRST); 1393 calNextAvail.setSkippedWallTimeOption(Calendar.WALLTIME_NEXT_VALID); 1394 1395 for (Object[] test : TESTDATA) { 1396 String tzid = (String)test[0]; 1397 TimeZone tz = TimeZone.getTimeZone(tzid); 1398 CalFields in = (CalFields)test[1]; 1399 boolean isValid = (Boolean)test[2]; 1400 CalFields expLastGMT = (CalFields)test[3]; 1401 CalFields expFirstGMT = (CalFields)test[4]; 1402 CalFields expNextAvailGMT = (CalFields)test[5]; 1403 1404 for (int i = 0; i < 2; i++) { 1405 boolean bLenient = (i == 0); 1406 1407 // WALLTIME_LAST 1408 calLast.setLenient(bLenient); 1409 calLast.setTimeZone(tz); 1410 try { 1411 in.setTo(calLast); 1412 calGMT.setTimeInMillis(calLast.getTimeInMillis()); 1413 CalFields outLastGMT = CalFields.createFrom(calGMT); 1414 if (!bLenient && !isValid) { 1415 errln("Fail: IllegalArgumentException expected - " + in + "[" + tzid + "] (WALLTIME_LAST)"); 1416 } else if (!outLastGMT.equals(expLastGMT)) { 1417 errln("Fail: WALLTIME_LAST " + in + "[" + tzid + "] is parsed as " + outLastGMT + "[GMT]. Expected: " + expLastGMT + "[GMT]"); 1418 } 1419 } catch (IllegalArgumentException e) { 1420 if (bLenient || isValid) { 1421 errln("Fail: Unexpected IllegalArgumentException - " + in + "[" + tzid + "] (WALLTIME_LAST)"); 1422 } 1423 } 1424 1425 // default 1426 calDefault.setLenient(bLenient); 1427 calDefault.setTimeZone(tz); 1428 try { 1429 in.setTo(calDefault); 1430 calGMT.setTimeInMillis(calDefault.getTimeInMillis()); 1431 CalFields outDefGMT = CalFields.createFrom(calGMT); 1432 if (!bLenient && !isValid) { 1433 errln("Fail: IllegalArgumentException expected - " + in + "[" + tzid + "] (default)"); 1434 } else if (!outDefGMT.equals(expLastGMT)) { 1435 errln("Fail: (default) " + in + "[" + tzid + "] is parsed as " + outDefGMT + "[GMT]. Expected: " + expLastGMT + "[GMT]"); 1436 } 1437 } catch (IllegalArgumentException e) { 1438 if (bLenient || isValid) { 1439 errln("Fail: Unexpected IllegalArgumentException - " + in + "[" + tzid + "] (default)"); 1440 } 1441 } 1442 1443 // WALLTIME_FIRST 1444 calFirst.setLenient(bLenient); 1445 calFirst.setTimeZone(tz); 1446 try { 1447 in.setTo(calFirst); 1448 calGMT.setTimeInMillis(calFirst.getTimeInMillis()); 1449 CalFields outFirstGMT = CalFields.createFrom(calGMT); 1450 if (!bLenient && !isValid) { 1451 errln("Fail: IllegalArgumentException expected - " + in + "[" + tzid + "] (WALLTIME_FIRST)"); 1452 } else if (!outFirstGMT.equals(expFirstGMT)) { 1453 errln("Fail: WALLTIME_FIRST " + in + "[" + tzid + "] is parsed as " + outFirstGMT + "[GMT]. Expected: " + expFirstGMT + "[GMT]"); 1454 } 1455 } catch (IllegalArgumentException e) { 1456 if (bLenient || isValid) { 1457 errln("Fail: Unexpected IllegalArgumentException - " + in + "[" + tzid + "] (WALLTIME_FIRST)"); 1458 } 1459 } 1460 1461 // WALLTIME_NEXT_VALID 1462 calNextAvail.setLenient(bLenient); 1463 calNextAvail.setTimeZone(tz); 1464 try { 1465 in.setTo(calNextAvail); 1466 calGMT.setTimeInMillis(calNextAvail.getTimeInMillis()); 1467 CalFields outNextAvailGMT = CalFields.createFrom(calGMT); 1468 if (!bLenient && !isValid) { 1469 errln("Fail: IllegalArgumentException expected - " + in + "[" + tzid + "] (WALLTIME_NEXT_VALID)"); 1470 } else if (!outNextAvailGMT.equals(expNextAvailGMT)) { 1471 errln("Fail: WALLTIME_NEXT_VALID " + in + "[" + tzid + "] is parsed as " + outNextAvailGMT + "[GMT]. Expected: " + expNextAvailGMT + "[GMT]"); 1472 } 1473 } catch (IllegalArgumentException e) { 1474 if (bLenient || isValid) { 1475 errln("Fail: Unexpected IllegalArgumentException - " + in + "[" + tzid + "] (WALLTIME_NEXT_VALID)"); 1476 } 1477 } 1478 } 1479 } 1480 } 1481 1482 @Test TestFieldDifference()1483 public void TestFieldDifference() { 1484 class TFDItem { 1485 public String tzname; 1486 public String locale; 1487 public long start; 1488 public long target; 1489 public boolean progressive; // true to compute progressive difference for each field, false to reset calendar after each call 1490 int yDiff; 1491 int MDiff; 1492 int dDiff; 1493 int HDiff; 1494 int mDiff; 1495 int sDiff; // 0x7FFFFFFF indicates overflow error expected 1496 // Simple constructor 1497 public TFDItem(String tz, String loc, long st, long tg, boolean prg, int yD, int MD, int dD, int HD, int mD, int sD ) { 1498 tzname = tz; 1499 locale = loc; 1500 start = st; 1501 target = tg; 1502 progressive = prg; 1503 yDiff = yD; 1504 MDiff = MD; 1505 dDiff = dD; 1506 HDiff = HD; 1507 mDiff = mD; 1508 sDiff = sD; 1509 } 1510 }; 1511 final TFDItem[] tfdItems = { 1512 // timezobe locale start target prog yDf MDf dDf HDf mDf sDf 1513 // For these we compute the progressive difference for each field - not resetting the calendar after each call 1514 new TFDItem( "US/Pacific", "en_US", 1267459800000L, 1277772600000L, true, 0, 3, 27, 9, 40, 0 ), // 2010-Mar-01 08:10 -> 2010-Jun-28 17:50 1515 new TFDItem( "US/Pacific", "en_US", 1267459800000L, 1299089280000L, true, 1, 0, 1, 1, 58, 0 ), // 2010-Mar-01 08:10 -> 2011-Mar-02 10:08 1516 // For these we compute the total difference for each field - resetting the calendar after each call 1517 new TFDItem( "GMT", "en_US", 0, 1073692800000L, false, 34, 408, 12427, 298248, 17894880, 1073692800 ), // 1970-Jan-01 00:00 -> 2004-Jan-10 00:00 1518 new TFDItem( "GMT", "en_US", 0, 1073779200000L, false, 34, 408, 12428, 298272, 17896320, 1073779200 ), // 1970-Jan-01 00:00 -> 2004-Jan-11 00:00 1519 new TFDItem( "GMT", "en_US", 0, 2147472000000L, false, 68, 816, 24855, 596520, 35791200, 2147472000 ), // 1970-Jan-01 00:00 -> 2038-Jan-19 00:00 1520 // new TFDItem( "GMT", "en_US", 0, 2147558400000L, false, 68, 816, 24856, 596544, 35792640, 0x7FFFFFFF ), // 1970-Jan-01 00:00 -> 2038-Jan-20 00:00, seconds overflow => exception in ICU4J 1521 new TFDItem( "GMT", "en_US", 0, -1073692800000L, false, -34,-408,-12427,-298248,-17894880,-1073692800 ), // 1970-Jan-01 00:00 -> 1935-Dec-24 00:00 1522 new TFDItem( "GMT", "en_US", 0, -1073779200000L, false, -34,-408,-12428,-298272,-17896320,-1073779200 ), // 1970-Jan-01 00:00 -> 1935-Dec-23 00:00 1523 // check fwd/backward on either side of era boundary and across era boundary 1524 new TFDItem( "GMT", "en_US", -61978089600000L,-61820409600000L, false, 4, 59, 1825, 43800, 2628000, 157680000 ), // CE 5-Dec-31 00:00 -> CE 10-Dec-30 00:00 1525 new TFDItem( "GMT", "en_US", -61820409600000L,-61978089600000L, false, -4, -59, -1825, -43800, -2628000, -157680000 ), // CE 10-Dec-30 00:00 -> CE 5-Dec-31 00:00 1526 new TFDItem( "GMT", "en_US", -62451129600000L,-62293449600000L, false, 4, 59, 1825, 43800, 2628000, 157680000 ), // BCE 10-Jan-04 00:00 -> BCE 5-Jan-03 00:00 1527 new TFDItem( "GMT", "en_US", -62293449600000L,-62451129600000L, false, -4, -59, -1825, -43800, -2628000, -157680000 ), // BCE 5-Jan-03 00:00 -> BCE 10-Jan-04 00:00 1528 new TFDItem( "GMT", "en_US", -62293449600000L,-61978089600000L, false, 9, 119, 3650, 87600, 5256000, 315360000 ), // BCE 5-Jan-03 00:00 -> CE 5-Dec-31 00:00 1529 new TFDItem( "GMT", "en_US", -61978089600000L,-62293449600000L, false, -9,-119, -3650, -87600, -5256000, -315360000 ), // CE 5-Dec-31 00:00 -> BCE 5-Jan-03 00:00 1530 new TFDItem( "GMT", "en@calendar=roc", -1672704000000L, -1515024000000L, false, 4, 59, 1825, 43800, 2628000, 157680000 ), // MG 5-Dec-30 00:00 -> MG 10-Dec-29 00:00 1531 new TFDItem( "GMT", "en@calendar=roc", -1515024000000L, -1672704000000L, false, -4, -59, -1825, -43800, -2628000, -157680000 ), // MG 10-Dec-29 00:00 -> MG 5-Dec-30 00:00 1532 new TFDItem( "GMT", "en@calendar=roc", -2145744000000L, -1988064000000L, false, 4, 59, 1825, 43800, 2628000, 157680000 ), // BMG 10-Jan-03 00:00 -> BMG 5-Jan-02 00:00 1533 new TFDItem( "GMT", "en@calendar=roc", -1988064000000L, -2145744000000L, false, -4, -59, -1825, -43800, -2628000, -157680000 ), // BMG 5-Jan-02 00:00 -> BMG 10-Jan-03 00:00 1534 new TFDItem( "GMT", "en@calendar=roc", -1988064000000L, -1672704000000L, false, 9, 119, 3650, 87600, 5256000, 315360000 ), // BMG 5-Jan-02 00:00 -> MG 5-Dec-30 00:00 1535 new TFDItem( "GMT", "en@calendar=roc", -1672704000000L, -1988064000000L, false, -9,-119, -3650, -87600, -5256000, -315360000 ), // MG 5-Dec-30 00:00 -> BMG 5-Jan-02 00:00 1536 new TFDItem( "GMT", "en@calendar=coptic",-53026531200000L,-52868851200000L, false, 4, 64, 1825, 43800, 2628000, 157680000 ), // Er1 5-Nas-05 00:00 -> Er1 10-Nas-04 00:00 1537 new TFDItem( "GMT", "en@calendar=coptic",-52868851200000L,-53026531200000L, false, -4, -64, -1825, -43800, -2628000, -157680000 ), // Er1 10-Nas-04 00:00 -> Er1 5-Nas-05 00:00 1538 new TFDItem( "GMT", "en@calendar=coptic",-53499571200000L,-53341891200000L, false, 4, 64, 1825, 43800, 2628000, 157680000 ), // Er0 10-Tou-04 00:00 -> Er0 5-Tou-02 00:00 1539 new TFDItem( "GMT", "en@calendar=coptic",-53341891200000L,-53499571200000L, false, -4, -64, -1825, -43800, -2628000, -157680000 ), // Er0 5-Tou-02 00:00 -> Er0 10-Tou-04 00:00 1540 new TFDItem( "GMT", "en@calendar=coptic",-53341891200000L,-53026531200000L, false, 9, 129, 3650, 87600, 5256000, 315360000 ), // Er0 5-Tou-02 00:00 -> Er1 5-Nas-05 00:00 1541 new TFDItem( "GMT", "en@calendar=coptic",-53026531200000L,-53341891200000L, false, -9,-129, -3650, -87600, -5256000, -315360000 ), // Er1 5-Nas-05 00:00 -> Er0 5-Tou-02 00:00 1542 }; 1543 for (TFDItem tfdItem: tfdItems) { 1544 TimeZone timezone = TimeZone.getFrozenTimeZone(tfdItem.tzname); 1545 Calendar ucal = Calendar.getInstance(timezone, new ULocale(tfdItem.locale)); 1546 ucal.setTimeInMillis(tfdItem.target); 1547 Date targetDate = ucal.getTime(); 1548 int yDf, MDf, dDf, HDf, mDf, sDf; 1549 if (tfdItem.progressive) { 1550 ucal.setTimeInMillis(tfdItem.start); 1551 yDf = ucal.fieldDifference(targetDate, YEAR); 1552 MDf = ucal.fieldDifference(targetDate, MONTH); 1553 dDf = ucal.fieldDifference(targetDate, DATE); 1554 HDf = ucal.fieldDifference(targetDate, HOUR); 1555 mDf = ucal.fieldDifference(targetDate, MINUTE); 1556 sDf = ucal.fieldDifference(targetDate, SECOND); 1557 if ( yDf != tfdItem.yDiff || MDf != tfdItem.MDiff || dDf != tfdItem.dDiff || HDf != tfdItem.HDiff || mDf != tfdItem.mDiff || sDf != tfdItem.sDiff ) { 1558 errln("Fail: for locale \"" + tfdItem.locale + "\", start " + tfdItem.start + ", target " + tfdItem.target + ", expected y-M-d-H-m-s progressive diffs " + 1559 tfdItem.yDiff +","+ tfdItem.MDiff +","+ tfdItem.dDiff +","+ tfdItem.HDiff +","+ tfdItem.mDiff +","+ tfdItem.sDiff + ", got " + 1560 yDf +","+ MDf +","+ dDf +","+ HDf +","+ mDf +","+ sDf); 1561 } 1562 } else { 1563 ucal.setTimeInMillis(tfdItem.start); 1564 yDf = ucal.fieldDifference(targetDate, YEAR); 1565 ucal.setTimeInMillis(tfdItem.start); 1566 MDf = ucal.fieldDifference(targetDate, MONTH); 1567 ucal.setTimeInMillis(tfdItem.start); 1568 dDf = ucal.fieldDifference(targetDate, DATE); 1569 ucal.setTimeInMillis(tfdItem.start); 1570 HDf = ucal.fieldDifference(targetDate, HOUR); 1571 ucal.setTimeInMillis(tfdItem.start); 1572 mDf = ucal.fieldDifference(targetDate, MINUTE); 1573 if ( yDf != tfdItem.yDiff || MDf != tfdItem.MDiff || dDf != tfdItem.dDiff || HDf != tfdItem.HDiff || mDf != tfdItem.mDiff ) { 1574 errln("Fail: for locale \"" + tfdItem.locale + "\", start " + tfdItem.start + ", target " + tfdItem.target + ", expected y-M-d-H-m total diffs " + 1575 tfdItem.yDiff +","+ tfdItem.MDiff +","+ tfdItem.dDiff +","+ tfdItem.HDiff +","+ tfdItem.mDiff + ", got " + 1576 yDf +","+ MDf +","+ dDf +","+ HDf +","+ mDf); 1577 } 1578 ucal.setTimeInMillis(tfdItem.start); 1579 sDf = ucal.fieldDifference(targetDate, SECOND); 1580 if ( sDf != 0x7FFFFFFF && sDf != tfdItem.sDiff ) { 1581 errln("Fail: for locale \"" + tfdItem.locale + "\", start " + tfdItem.start + ", target " + tfdItem.target + ", expected seconds total diffs " + 1582 tfdItem.sDiff + ", got " + sDf); 1583 } 1584 } 1585 } 1586 } 1587 1588 @Test TestAddRollEra0AndEraBounds()1589 public void TestAddRollEra0AndEraBounds() { 1590 final String[] localeIDs = { 1591 // calendars with non-modern era 0 that goes backwards, max era == 1 1592 "en@calendar=gregorian", 1593 "en@calendar=roc", 1594 "en@calendar=coptic", 1595 // calendars with non-modern era 0 that goes forwards, max era > 1 1596 "en@calendar=japanese", 1597 "en@calendar=chinese", 1598 // calendars with non-modern era 0 that goes forwards, max era == 1 1599 "en@calendar=ethiopic", 1600 // calendars with only one era = 0, forwards 1601 "en@calendar=buddhist", 1602 "en@calendar=hebrew", 1603 "en@calendar=islamic", 1604 "en@calendar=indian", 1605 //"en@calendar=persian", // no persian calendar in ICU4J yet 1606 "en@calendar=ethiopic-amete-alem", 1607 }; 1608 TimeZone zoneGMT = TimeZone.getFrozenTimeZone("GMT"); 1609 for (String localeID : localeIDs) { 1610 Calendar ucalTest = Calendar.getInstance(zoneGMT, new ULocale(localeID)); 1611 String calType = ucalTest.getType(); 1612 boolean era0YearsGoBackwards = (calType.equals("gregorian") || calType.equals("roc") || calType.equals("coptic")); 1613 int yrBefore, yrAfter, yrMax, eraAfter, eraMax, eraNow; 1614 1615 ucalTest.clear(); 1616 ucalTest.set(Calendar.YEAR, 2); 1617 ucalTest.set(Calendar.ERA, 0); 1618 yrBefore = ucalTest.get(Calendar.YEAR); 1619 ucalTest.add(Calendar.YEAR, 1); 1620 yrAfter = ucalTest.get(Calendar.YEAR); 1621 if ( (era0YearsGoBackwards && yrAfter>yrBefore) || (!era0YearsGoBackwards && yrAfter<yrBefore) ) { 1622 errln("Fail: era 0 add 1 year does not move forward in time for " + localeID); 1623 } 1624 1625 ucalTest.clear(); 1626 ucalTest.set(Calendar.YEAR, 2); 1627 ucalTest.set(Calendar.ERA, 0); 1628 yrBefore = ucalTest.get(Calendar.YEAR); 1629 ucalTest.roll(Calendar.YEAR, 1); 1630 yrAfter = ucalTest.get(Calendar.YEAR); 1631 if ( (era0YearsGoBackwards && yrAfter>yrBefore) || (!era0YearsGoBackwards && yrAfter<yrBefore) ) { 1632 errln("Fail: era 0 roll 1 year does not move forward in time for " + localeID); 1633 } 1634 1635 ucalTest.clear(); 1636 ucalTest.set(Calendar.YEAR, 1); 1637 ucalTest.set(Calendar.ERA, 0); 1638 if (era0YearsGoBackwards) { 1639 ucalTest.roll(Calendar.YEAR, 1); 1640 yrAfter = ucalTest.get(Calendar.YEAR); 1641 eraAfter = ucalTest.get(Calendar.ERA); 1642 if (eraAfter != 0 || yrAfter != 1) { 1643 errln("Fail: era 0 roll 1 year from year 1 does not stay within era or pin to year 1 for " 1644 + localeID + " (get era " + eraAfter + " year " + yrAfter + ")"); 1645 } 1646 } else { 1647 // roll backward in time to where era 0 years go negative, except for the Chinese 1648 // calendar, which uses negative eras instead of having years outside the range 1-60 1649 ucalTest.roll(Calendar.YEAR, -2); 1650 yrAfter = ucalTest.get(Calendar.YEAR); 1651 eraAfter = ucalTest.get(Calendar.ERA); 1652 if ( !calType.equals("chinese") && (eraAfter != 0 || yrAfter != -1) ) { 1653 errln("Fail: era 0 roll -2 years from year 1 does not stay within era or produce year -1 for " 1654 + localeID + " (get era " + eraAfter + " year " + yrAfter + ")"); 1655 } 1656 } 1657 1658 ucalTest.clear(); 1659 { 1660 int eraMin = ucalTest.getMinimum(Calendar.ERA); 1661 if (eraMin != 0 && calType.compareTo("chinese") != 0) { 1662 errln("Fail: getMinimum returns minimum era " + eraMin + " (should be 0) for calType " + calType); 1663 } 1664 } 1665 1666 ucalTest.clear(); 1667 ucalTest.set(Calendar.YEAR, 1); 1668 ucalTest.set(Calendar.ERA, 0); 1669 eraMax = ucalTest.getMaximum(Calendar.ERA); 1670 if (eraMax > 0) { 1671 // try similar tests for era 1 (if calendar has it), in which years always go forward 1672 1673 ucalTest.clear(); 1674 ucalTest.set(Calendar.YEAR, 2); 1675 ucalTest.set(Calendar.ERA, 1); 1676 yrBefore = ucalTest.get(Calendar.YEAR); 1677 ucalTest.add(Calendar.YEAR, 1); 1678 yrAfter = ucalTest.get(Calendar.YEAR); 1679 if ( yrAfter<yrBefore ) { 1680 errln("Fail: era 1 add 1 year does not move forward in time for " + localeID); 1681 } 1682 1683 ucalTest.clear(); 1684 ucalTest.set(Calendar.YEAR, 2); 1685 ucalTest.set(Calendar.ERA, 1); 1686 yrBefore = ucalTest.get(Calendar.YEAR); 1687 ucalTest.roll(Calendar.YEAR, 1); 1688 yrAfter = ucalTest.get(Calendar.YEAR); 1689 if ( yrAfter<yrBefore ) { 1690 errln("Fail: era 1 roll 1 year does not move forward in time for " + localeID); 1691 } 1692 1693 ucalTest.clear(); 1694 ucalTest.set(Calendar.YEAR, 1); 1695 ucalTest.set(Calendar.ERA, 1); 1696 yrMax = ucalTest.getActualMaximum(Calendar.YEAR); 1697 ucalTest.roll(Calendar.YEAR, -1); // roll down which should pin or wrap to end 1698 yrAfter = ucalTest.get(Calendar.YEAR); 1699 eraAfter = ucalTest.get(Calendar.ERA); 1700 // if yrMax is reasonable we should wrap to that, else we should pin at yr 1 1701 if (yrMax >= 32768) { 1702 if (eraAfter != 1 || yrAfter != 1) { 1703 errln("Fail: era 1 roll -1 year from year 1 does not stay within era or pin to year 1 for " 1704 + localeID + " (get era " + eraAfter + " year " + yrAfter + ")"); 1705 } 1706 } else if (eraAfter != 1 || yrAfter != yrMax) { 1707 errln("Fail: era 1 roll -1 year from year 1 does not stay within era or wrap to year " 1708 + yrMax + " for " + localeID + " (get era " + eraAfter + " year " + yrAfter + ")"); 1709 } else { 1710 ucalTest.roll(Calendar.YEAR, 1); // now roll up which should wrap to beginning 1711 yrAfter = ucalTest.get(Calendar.YEAR); 1712 eraAfter = ucalTest.get(Calendar.ERA); 1713 if (eraAfter != 1 || yrAfter != 1) { 1714 errln("Fail: era 1 roll 1 year from year " + yrMax + 1715 " does not stay within era or wrap to year 1 for " 1716 + localeID + " (get era " + eraAfter + " year " + yrAfter + ")"); 1717 } 1718 } 1719 1720 // if current era > 1, try the same roll tests for current era 1721 ucalTest.setTime(new Date()); 1722 eraNow = ucalTest.get(Calendar.ERA); 1723 if (eraNow > 1) { 1724 ucalTest.clear(); 1725 ucalTest.set(Calendar.YEAR, 1); 1726 ucalTest.set(Calendar.ERA, eraNow); 1727 yrMax = ucalTest.getActualMaximum(Calendar.YEAR); // max year value for this era 1728 ucalTest.roll(Calendar.YEAR, -1); 1729 yrAfter = ucalTest.get(Calendar.YEAR); 1730 eraAfter = ucalTest.get(Calendar.ERA); 1731 // if yrMax is reasonable we should wrap to that, else we should pin at yr 1 1732 if (yrMax >= 32768) { 1733 if (eraAfter != eraNow || yrAfter != 1) { 1734 errln("Fail: era " + eraNow + 1735 " roll -1 year from year 1 does not stay within era or pin to year 1 for " 1736 + localeID + " (get era " + eraAfter + " year " + yrAfter + ")"); 1737 } 1738 } else if (eraAfter != eraNow || yrAfter != yrMax) { 1739 errln("Fail: era " + eraNow + 1740 " roll -1 year from year 1 does not stay within era or wrap to year " + yrMax 1741 + " for " + localeID + " (get era " + eraAfter + " year " + yrAfter + ")"); 1742 } else { 1743 ucalTest.roll(Calendar.YEAR, 1); // now roll up which should wrap to beginning 1744 yrAfter = ucalTest.get(Calendar.YEAR); 1745 eraAfter = ucalTest.get(Calendar.ERA); 1746 if (eraAfter != eraNow || yrAfter != 1) { 1747 errln("Fail: era " + eraNow + " roll 1 year from year " + yrMax + 1748 " does not stay within era or wrap to year 1 for " 1749 + localeID + " (get era " + eraAfter + " year " + yrAfter + ")"); 1750 } 1751 } 1752 } 1753 } 1754 } 1755 } 1756 1757 @Test TestWeekData()1758 public void TestWeekData() { 1759 // Each line contains two locales using the same set of week rule data. 1760 final String LOCALE_PAIRS[] = { 1761 "en", "en_US", 1762 "de", "de_DE", 1763 "de_DE", "en_DE", 1764 "en_GB", "und_GB", 1765 "ar_EG", "en_EG", 1766 "ar_SA", "fr_SA", 1767 }; 1768 1769 for (int i = 0; i < LOCALE_PAIRS.length; i += 2) { 1770 Calendar cal1 = Calendar.getInstance(new ULocale(LOCALE_PAIRS[i])); 1771 Calendar cal2 = Calendar.getInstance(new ULocale(LOCALE_PAIRS[i + 1])); 1772 1773 // First day of week 1774 int dow1 = cal1.getFirstDayOfWeek(); 1775 int dow2 = cal2.getFirstDayOfWeek(); 1776 if (dow1 != dow2) { 1777 errln("getFirstDayOfWeek: " + LOCALE_PAIRS[i] + "->" + dow1 + ", " + LOCALE_PAIRS[i + 1] + "->" + dow2); 1778 } 1779 1780 // Minimum days in first week 1781 int minDays1 = cal1.getMinimalDaysInFirstWeek(); 1782 int minDays2 = cal2.getMinimalDaysInFirstWeek(); 1783 if (minDays1 != minDays2) { 1784 errln("getMinimalDaysInFirstWeek: " + LOCALE_PAIRS[i] + "->" + minDays1 + ", " + LOCALE_PAIRS[i + 1] + "->" + minDays2); 1785 } 1786 1787 // Weekdays and Weekends 1788 for (int d = Calendar.SUNDAY; d <= Calendar.SATURDAY; d++) { 1789 int wdt1 = cal1.getDayOfWeekType(d); 1790 int wdt2 = cal2.getDayOfWeekType(d); 1791 if (wdt1 != wdt2) { 1792 errln("getDayOfWeekType(" + d + "): " + LOCALE_PAIRS[i] + "->" + wdt1 + ", " + LOCALE_PAIRS[i + 1] + "->" + wdt2); 1793 } 1794 } 1795 } 1796 } 1797 1798 @Test TestAddAcrossZoneTransition()1799 public void TestAddAcrossZoneTransition() { 1800 class TestData { 1801 String zone; 1802 CalFields base; 1803 int deltaDays; 1804 int skippedWTOpt; 1805 CalFields expected; 1806 1807 TestData(String zone, CalFields base, int deltaDays, int skippedWTOpt, CalFields expected) { 1808 this.zone = zone; 1809 this.base = base; 1810 this.deltaDays = deltaDays; 1811 this.skippedWTOpt = skippedWTOpt; 1812 this.expected = expected; 1813 } 1814 } 1815 1816 TestData[] data = new TestData[] { 1817 // Add 1 day, from the date before DST transition 1818 new TestData("America/Los_Angeles", new CalFields(2014, 3, 8, 1, 59, 59, 999), 1, Calendar.WALLTIME_FIRST, 1819 new CalFields(2014, 3, 9, 1, 59, 59, 999)), 1820 1821 new TestData("America/Los_Angeles", new CalFields(2014, 3, 8, 1, 59, 59, 999), 1, Calendar.WALLTIME_LAST, 1822 new CalFields(2014, 3, 9, 1, 59, 59, 999)), 1823 1824 new TestData("America/Los_Angeles", new CalFields(2014, 3, 8, 1, 59, 59, 999), 1, Calendar.WALLTIME_NEXT_VALID, 1825 new CalFields(2014, 3, 9, 1, 59, 59, 999)), 1826 1827 1828 new TestData("America/Los_Angeles", new CalFields(2014, 3, 8, 2, 0, 0, 0), 1, Calendar.WALLTIME_FIRST, 1829 new CalFields(2014, 3, 9, 1, 0, 0, 0)), 1830 1831 new TestData("America/Los_Angeles", new CalFields(2014, 3, 8, 2, 0, 0, 0), 1, Calendar.WALLTIME_LAST, 1832 new CalFields(2014, 3, 9, 3, 0, 0, 0)), 1833 1834 new TestData("America/Los_Angeles", new CalFields(2014, 3, 8, 2, 0, 0, 0), 1, Calendar.WALLTIME_NEXT_VALID, 1835 new CalFields(2014, 3, 9, 3, 0, 0, 0)), 1836 1837 1838 new TestData("America/Los_Angeles", new CalFields(2014, 3, 8, 2, 30, 0, 0), 1, Calendar.WALLTIME_FIRST, 1839 new CalFields(2014, 3, 9, 1, 30, 0, 0)), 1840 1841 new TestData("America/Los_Angeles", new CalFields(2014, 3, 8, 2, 30, 0, 0), 1, Calendar.WALLTIME_LAST, 1842 new CalFields(2014, 3, 9, 3, 30, 0, 0)), 1843 1844 new TestData("America/Los_Angeles", new CalFields(2014, 3, 8, 2, 30, 0, 0), 1, Calendar.WALLTIME_NEXT_VALID, 1845 new CalFields(2014, 3, 9, 3, 0, 0, 0)), 1846 1847 1848 new TestData("America/Los_Angeles", new CalFields(2014, 3, 8, 3, 0, 0, 0), 1, Calendar.WALLTIME_FIRST, 1849 new CalFields(2014, 3, 9, 3, 0, 0, 0)), 1850 1851 new TestData("America/Los_Angeles", new CalFields(2014, 3, 8, 3, 0, 0, 0), 1, Calendar.WALLTIME_LAST, 1852 new CalFields(2014, 3, 9, 3, 0, 0, 0)), 1853 1854 new TestData("America/Los_Angeles", new CalFields(2014, 3, 8, 3, 0, 0, 0), 1, Calendar.WALLTIME_NEXT_VALID, 1855 new CalFields(2014, 3, 9, 3, 0, 0, 0)), 1856 1857 1858 // Subtract 1 day, from one day after DST transition 1859 new TestData("America/Los_Angeles", new CalFields(2014, 3, 10, 1, 59, 59, 999), -1, Calendar.WALLTIME_FIRST, 1860 new CalFields(2014, 3, 9, 1, 59, 59, 999)), 1861 1862 new TestData("America/Los_Angeles", new CalFields(2014, 3, 10, 1, 59, 59, 999), -1, Calendar.WALLTIME_LAST, 1863 new CalFields(2014, 3, 9, 1, 59, 59, 999)), 1864 1865 new TestData("America/Los_Angeles", new CalFields(2014, 3, 10, 1, 59, 59, 999), -1, Calendar.WALLTIME_NEXT_VALID, 1866 new CalFields(2014, 3, 9, 1, 59, 59, 999)), 1867 1868 1869 new TestData("America/Los_Angeles", new CalFields(2014, 3, 10, 2, 0, 0, 0), -1, Calendar.WALLTIME_FIRST, 1870 new CalFields(2014, 3, 9, 1, 0, 0, 0)), 1871 1872 new TestData("America/Los_Angeles", new CalFields(2014, 3, 10, 2, 0, 0, 0), -1, Calendar.WALLTIME_LAST, 1873 new CalFields(2014, 3, 9, 3, 0, 0, 0)), 1874 1875 new TestData("America/Los_Angeles", new CalFields(2014, 3, 10, 2, 0, 0, 0), -1, Calendar.WALLTIME_NEXT_VALID, 1876 new CalFields(2014, 3, 9, 3, 0, 0, 0)), 1877 1878 1879 new TestData("America/Los_Angeles", new CalFields(2014, 3, 10, 2, 30, 0, 0), -1, Calendar.WALLTIME_FIRST, 1880 new CalFields(2014, 3, 9, 1, 30, 0, 0)), 1881 1882 new TestData("America/Los_Angeles", new CalFields(2014, 3, 10, 2, 30, 0, 0), -1, Calendar.WALLTIME_LAST, 1883 new CalFields(2014, 3, 9, 3, 30, 0, 0)), 1884 1885 new TestData("America/Los_Angeles", new CalFields(2014, 3, 10, 2, 30, 0, 0), -1, Calendar.WALLTIME_NEXT_VALID, 1886 new CalFields(2014, 3, 9, 3, 0, 0, 0)), 1887 1888 1889 new TestData("America/Los_Angeles", new CalFields(2014, 3, 10, 3, 0, 0, 0), -1, Calendar.WALLTIME_FIRST, 1890 new CalFields(2014, 3, 9, 3, 0, 0, 0)), 1891 1892 new TestData("America/Los_Angeles", new CalFields(2014, 3, 10, 3, 0, 0, 0), -1, Calendar.WALLTIME_LAST, 1893 new CalFields(2014, 3, 9, 3, 0, 0, 0)), 1894 1895 new TestData("America/Los_Angeles", new CalFields(2014, 3, 10, 3, 0, 0, 0), -1, Calendar.WALLTIME_NEXT_VALID, 1896 new CalFields(2014, 3, 9, 3, 0, 0, 0)), 1897 1898 1899 // Test case for ticket#10544 1900 new TestData("America/Santiago", new CalFields(2013, 4, 27, 0, 0, 0, 0), 134, Calendar.WALLTIME_FIRST, 1901 new CalFields(2013, 9, 7, 23, 0, 0, 0)), 1902 1903 new TestData("America/Santiago", new CalFields(2013, 4, 27, 0, 0, 0, 0), 134, Calendar.WALLTIME_LAST, 1904 new CalFields(2013, 9, 8, 1, 0, 0, 0)), 1905 1906 new TestData("America/Santiago", new CalFields(2013, 4, 27, 0, 0, 0, 0), 134, Calendar.WALLTIME_NEXT_VALID, 1907 new CalFields(2013, 9, 8, 1, 0, 0, 0)), 1908 1909 1910 new TestData("America/Santiago", new CalFields(2013, 4, 27, 0, 30, 0, 0), 134, Calendar.WALLTIME_FIRST, 1911 new CalFields(2013, 9, 7, 23, 30, 0, 0)), 1912 1913 new TestData("America/Santiago", new CalFields(2013, 4, 27, 0, 30, 0, 0), 134, Calendar.WALLTIME_LAST, 1914 new CalFields(2013, 9, 8, 1, 30, 0, 0)), 1915 1916 new TestData("America/Santiago", new CalFields(2013, 4, 27, 0, 30, 0, 0), 134, Calendar.WALLTIME_NEXT_VALID, 1917 new CalFields(2013, 9, 8, 1, 0, 0, 0)), 1918 1919 1920 // Extreme transition - Pacific/Apia completely skips 2011-12-30 1921 new TestData("Pacific/Apia", new CalFields(2011, 12, 29, 0, 0, 0, 0), 1, Calendar.WALLTIME_FIRST, 1922 new CalFields(2011, 12, 31, 0, 0, 0, 0)), 1923 1924 new TestData("Pacific/Apia", new CalFields(2011, 12, 29, 0, 0, 0, 0), 1, Calendar.WALLTIME_LAST, 1925 new CalFields(2011, 12, 31, 0, 0, 0, 0)), 1926 1927 new TestData("Pacific/Apia", new CalFields(2011, 12, 29, 0, 0, 0, 0), 1, Calendar.WALLTIME_NEXT_VALID, 1928 new CalFields(2011, 12, 31, 0, 0, 0, 0)), 1929 1930 1931 new TestData("Pacific/Apia", new CalFields(2011, 12, 31, 12, 0, 0, 0), -1, Calendar.WALLTIME_FIRST, 1932 new CalFields(2011, 12, 29, 12, 0, 0, 0)), 1933 1934 new TestData("Pacific/Apia", new CalFields(2011, 12, 31, 12, 0, 0, 0), -1, Calendar.WALLTIME_LAST, 1935 new CalFields(2011, 12, 29, 12, 0, 0, 0)), 1936 1937 new TestData("Pacific/Apia", new CalFields(2011, 12, 31, 12, 0, 0, 0), -1, Calendar.WALLTIME_NEXT_VALID, 1938 new CalFields(2011, 12, 29, 12, 0, 0, 0)), 1939 1940 1941 // 30 minutes DST - Australia/Lord_Howe 1942 new TestData("Australia/Lord_Howe", new CalFields(2013, 10, 5, 2, 15, 0, 0), 1, Calendar.WALLTIME_FIRST, 1943 new CalFields(2013, 10, 6, 1, 45, 0, 0)), 1944 1945 new TestData("Australia/Lord_Howe", new CalFields(2013, 10, 5, 2, 15, 0, 0), 1, Calendar.WALLTIME_LAST, 1946 new CalFields(2013, 10, 6, 2, 45, 0, 0)), 1947 1948 new TestData("Australia/Lord_Howe", new CalFields(2013, 10, 5, 2, 15, 0, 0), 1, Calendar.WALLTIME_NEXT_VALID, 1949 new CalFields(2013, 10, 6, 2, 30, 0, 0)), 1950 }; 1951 1952 Calendar cal = Calendar.getInstance(); 1953 for (TestData d : data) { 1954 cal.setTimeZone(TimeZone.getTimeZone(d.zone)); 1955 cal.setSkippedWallTimeOption(d.skippedWTOpt); 1956 d.base.setTo(cal); 1957 cal.add(Calendar.DATE, d.deltaDays); 1958 1959 if (!d.expected.isEquivalentTo(cal)) { 1960 CalFields res = CalFields.createFrom(cal); 1961 String optDisp = d.skippedWTOpt == Calendar.WALLTIME_FIRST ? "FIRST" : 1962 d.skippedWTOpt == Calendar.WALLTIME_LAST ? "LAST" : "NEXT_VALID"; 1963 errln("Error: base:" + d.base.toString() + ", tz:" + d.zone 1964 + ", delta:" + d.deltaDays + " day(s), opt:" + optDisp 1965 + ", result:" + res.toString() + " - expected:" + d.expected.toString()); 1966 } 1967 } 1968 } 1969 1970 @Test TestSimpleDateFormatCoverage()1971 public void TestSimpleDateFormatCoverage() { 1972 1973 class StubSimpleDateFormat extends SimpleDateFormat { 1974 private static final long serialVersionUID = 1L; 1975 1976 public StubSimpleDateFormat(String pattern, Locale loc) { 1977 new SimpleDateFormat(pattern, loc); 1978 } 1979 1980 public void run(){ 1981 Calendar cal = Calendar.getInstance(Locale.US); 1982 cal.clear(); 1983 cal.set(2000, Calendar.MARCH, 18, 15, 0, 1); // Sat 15:00 1984 1985 DateFormatSymbols theseSymbols = this.getSymbols(); 1986 String shouldBeMonday = theseSymbols.getWeekdays()[Calendar.MONDAY]; 1987 assertEquals("Should be Monday", "Monday", shouldBeMonday); 1988 1989 String [] matchData = {"16", "2016", "2016AD", "Monday", "lunes"}; 1990 int matchIndex = matchString("Monday March 28, 2016", 0, Calendar.DAY_OF_WEEK, matchData, cal); 1991 assertEquals("matchData for Monday", 6, matchIndex); // Position of the pointer after the matched string. 1992 matchIndex = matchString("Monday March 28, 2016 AD", 17, Calendar.YEAR, matchData, cal); 1993 assertEquals("matchData for 2016", 21, matchIndex); // Position of the pointer after the matched string. 1994 1995 char ch = 'y'; 1996 int count = 4; 1997 int beginOffset = 0; 1998 cal.set(Calendar.YEAR, 2000); // Reset this 1999 assertEquals("calendar year reset", 2000, cal.get(Calendar.YEAR)); 2000 FieldPosition pos = new FieldPosition(java.text.DateFormat.YEAR_FIELD); 2001 String subFormatResult = subFormat(ch, count, beginOffset, 2002 pos, theseSymbols, cal); 2003 assertEquals("subFormat result", "2000", subFormatResult); 2004 2005 String testParseString = "some text with a date 2017-03-15"; 2006 int start = 22; 2007 boolean obeyCount = true; 2008 boolean allowNegative = false; 2009 boolean ambiguousYear[] = {true, false, true}; 2010 int subParseResult = subParse(testParseString, start, ch, count, 2011 obeyCount, allowNegative, ambiguousYear, cal); 2012 assertEquals("subParseResult result", 26, subParseResult); 2013 assertEquals("parsed year", 2017, cal.get(Calendar.YEAR)); 2014 } 2015 } 2016 StubSimpleDateFormat stub = new StubSimpleDateFormat("EEE MMM dd yyyy G HH:mm:ss.SSS", Locale.US); 2017 stub.run(); 2018 } 2019 } 2020