2 *******************************************************************************
\r
3 * Copyright (C) 2000-2009, International Business Machines Corporation and
\r
4 * others. All Rights Reserved.
\r
5 *******************************************************************************
\r
7 package com.ibm.icu.dev.test.calendar;
\r
9 import java.util.Date;
\r
10 import java.util.Locale;
\r
11 import java.text.ParseException;
\r
13 import com.ibm.icu.impl.LocaleUtility;
\r
14 import com.ibm.icu.impl.ZoneMeta;
\r
15 import com.ibm.icu.impl.CalendarAstronomer;
\r
16 import com.ibm.icu.text.DateFormat;
\r
17 import com.ibm.icu.text.SimpleDateFormat;
\r
18 import com.ibm.icu.util.*;
\r
21 * @summary Tests of new functionality in IBMCalendar
\r
23 public class IBMCalendarTest extends CalendarTest {
\r
25 public static void main(String[] args) throws Exception {
\r
26 new IBMCalendarTest().run(args);
\r
30 * Test weekend support in IBMCalendar.
\r
32 * NOTE: This test will have to be updated when the isWeekend() etc.
\r
33 * API is finalized later.
\r
35 * In particular, the test will have to be rewritten to instantiate
\r
36 * a Calendar in the given locale (using getInstance()) and call
\r
37 * that Calendar's isWeekend() etc. methods.
\r
39 public void TestWeekend() {
\r
40 SimpleDateFormat fmt = new SimpleDateFormat("EEE MMM dd yyyy G HH:mm:ss.SSS");
\r
43 // This test tests for specific locale data. This is probably okay
\r
44 // as far as US data is concerned, but if the Arabic/Yemen data
\r
45 // changes, this test will have to be updated.
\r
47 // Test specific days
\r
49 Locale.US, new int[] { // Saturday:Sunday
\r
50 2000, Calendar.MARCH, 17, 23, 0, 0, // Fri 23:00
\r
51 2000, Calendar.MARCH, 18, 0, -1, 0, // Fri 23:59:59.999
\r
52 2000, Calendar.MARCH, 18, 0, 0, 1, // Sat 00:00
\r
53 2000, Calendar.MARCH, 18, 15, 0, 1, // Sat 15:00
\r
54 2000, Calendar.MARCH, 19, 23, 0, 1, // Sun 23:00
\r
55 2000, Calendar.MARCH, 20, 0, -1, 1, // Sun 23:59:59.999
\r
56 2000, Calendar.MARCH, 20, 0, 0, 0, // Mon 00:00
\r
57 2000, Calendar.MARCH, 20, 8, 0, 0, // Mon 08:00
\r
59 new Locale("ar", "YE"), new int[] { // Thursday:Friday
\r
60 2000, Calendar.MARCH, 15, 23, 0, 0, // Wed 23:00
\r
61 2000, Calendar.MARCH, 16, 0, -1, 0, // Wed 23:59:59.999
\r
62 2000, Calendar.MARCH, 16, 0, 0, 1, // Thu 00:00
\r
63 2000, Calendar.MARCH, 16, 15, 0, 1, // Thu 15:00
\r
64 2000, Calendar.MARCH, 17, 23, 0, 1, // Fri 23:00
\r
65 2000, Calendar.MARCH, 18, 0, -1, 1, // Fri 23:59:59.999
\r
66 2000, Calendar.MARCH, 18, 0, 0, 0, // Sat 00:00
\r
67 2000, Calendar.MARCH, 18, 8, 0, 0, // Sat 08:00
\r
71 // Test days of the week
\r
73 Locale.US, new int[] {
\r
74 Calendar.MONDAY, Calendar.WEEKDAY,
\r
75 Calendar.FRIDAY, Calendar.WEEKDAY,
\r
76 Calendar.SATURDAY, Calendar.WEEKEND,
\r
77 Calendar.SUNDAY, Calendar.WEEKEND_CEASE,
\r
79 new Locale("ar", "YE"), new int[] { // Thursday:Friday
\r
80 Calendar.WEDNESDAY,Calendar.WEEKDAY,
\r
81 Calendar.SATURDAY, Calendar.WEEKDAY,
\r
82 Calendar.THURSDAY, Calendar.WEEKEND,
\r
83 Calendar.FRIDAY, Calendar.WEEKEND_CEASE,
\r
87 // We only test the getDayOfWeekType() and isWeekend() APIs.
\r
88 // The getWeekendTransition() API is tested indirectly via the
\r
89 // isWeekend() API, which calls it.
\r
91 for (int i1=0; i1<DATA1.length; i1+=2) {
\r
92 Locale loc = (Locale)DATA1[i1];
\r
93 int[] data = (int[]) DATA1[i1+1];
\r
94 Calendar cal = Calendar.getInstance(loc);
\r
95 logln("Locale: " + loc);
\r
96 for (int i=0; i<data.length; i+=6) {
\r
98 cal.set(data[i], data[i+1], data[i+2], data[i+3], 0, 0);
\r
99 if (data[i+4] != 0) {
\r
100 cal.setTime(new Date(cal.getTime().getTime() + data[i+4]));
\r
102 boolean isWeekend = cal.isWeekend();
\r
103 boolean ok = isWeekend == (data[i+5] != 0);
\r
105 logln("Ok: " + fmt.format(cal.getTime()) + " isWeekend=" + isWeekend);
\r
107 errln("FAIL: " + fmt.format(cal.getTime()) + " isWeekend=" + isWeekend +
\r
108 ", expected=" + (!isWeekend));
\r
113 for (int i2=0; i2<DATA2.length; i2+=2) {
\r
114 Locale loc = (Locale)DATA2[i2];
\r
115 int[] data = (int[]) DATA2[i2+1];
\r
116 logln("Locale: " + loc);
\r
117 Calendar cal = Calendar.getInstance(loc);
\r
118 for (int i=0; i<data.length; i+=2) {
\r
119 int type = cal.getDayOfWeekType(data[i]);
\r
120 int exp = data[i+1];
\r
122 logln("Ok: DOW " + data[i] + " type=" + type);
\r
124 errln("FAIL: DOW " + data[i] + " type=" + type +
\r
125 ", expected=" + exp);
\r
132 * Run a test of a quasi-Gregorian calendar. This is a calendar
\r
133 * that behaves like a Gregorian but has different year/era mappings.
\r
134 * The int[] data array should have the format:
\r
136 * { era, year, gregorianYear, month, dayOfMonth, ... }
\r
138 void quasiGregorianTest(Calendar cal, int[] data) {
\r
139 // As of JDK 1.4.1_01, using the Sun JDK GregorianCalendar as
\r
140 // a reference throws us off by one hour. This is most likely
\r
141 // due to the JDK 1.4 incorporation of historical time zones.
\r
142 //java.util.Calendar grego = java.util.Calendar.getInstance();
\r
143 Calendar grego = Calendar.getInstance();
\r
144 for (int i=0; i<data.length; ) {
\r
145 int era = data[i++];
\r
146 int year = data[i++];
\r
147 int gregorianYear = data[i++];
\r
148 int month = data[i++];
\r
149 int dayOfMonth = data[i++];
\r
152 grego.set(gregorianYear, month, dayOfMonth);
\r
153 Date D = grego.getTime();
\r
156 cal.set(Calendar.ERA, era);
\r
157 cal.set(year, month, dayOfMonth);
\r
158 Date d = cal.getTime();
\r
160 logln("OK: " + era + ":" + year + "/" + (month+1) + "/" + dayOfMonth +
\r
163 errln("Fail: " + era + ":" + year + "/" + (month+1) + "/" + dayOfMonth +
\r
164 " => " + d + ", expected " + D);
\r
169 int e = cal.get(Calendar.ERA);
\r
170 int y = cal.get(Calendar.YEAR);
\r
171 if (y == year && e == era) {
\r
172 logln("OK: " + D + " => " + cal.get(Calendar.ERA) + ":" +
\r
173 cal.get(Calendar.YEAR) + "/" +
\r
174 (cal.get(Calendar.MONTH)+1) + "/" + cal.get(Calendar.DATE));
\r
176 logln("Fail: " + D + " => " + cal.get(Calendar.ERA) + ":" +
\r
177 cal.get(Calendar.YEAR) + "/" +
\r
178 (cal.get(Calendar.MONTH)+1) + "/" + cal.get(Calendar.DATE) +
\r
179 ", expected " + era + ":" + year + "/" + (month+1) + "/" +
\r
186 * Verify that BuddhistCalendar shifts years to Buddhist Era but otherwise
\r
187 * behaves like GregorianCalendar.
\r
189 public void TestBuddhist() {
\r
190 quasiGregorianTest(new BuddhistCalendar(),
\r
192 // BE 2542 == 1999 CE
\r
193 0, 2542, 1999, Calendar.JUNE, 4
\r
197 public void TestBuddhistCoverage() {
\r
199 // new BuddhistCalendar(ULocale)
\r
200 BuddhistCalendar cal = new BuddhistCalendar(ULocale.getDefault());
\r
202 errln("could not create BuddhistCalendar with ULocale");
\r
207 // new BuddhistCalendar(TimeZone,ULocale)
\r
208 BuddhistCalendar cal = new BuddhistCalendar(TimeZone.getDefault(),ULocale.getDefault());
\r
210 errln("could not create BuddhistCalendar with TimeZone ULocale");
\r
215 // new BuddhistCalendar(TimeZone)
\r
216 BuddhistCalendar cal = new BuddhistCalendar(TimeZone.getDefault());
\r
218 errln("could not create BuddhistCalendar with TimeZone");
\r
223 // new BuddhistCalendar(Locale)
\r
224 BuddhistCalendar cal = new BuddhistCalendar(Locale.getDefault());
\r
226 errln("could not create BuddhistCalendar with Locale");
\r
231 // new BuddhistCalendar(TimeZone, Locale)
\r
232 BuddhistCalendar cal = new BuddhistCalendar(TimeZone.getDefault(), Locale.getDefault());
\r
234 errln("could not create BuddhistCalendar with TimeZone and Locale");
\r
239 // new BuddhistCalendar(Date)
\r
240 BuddhistCalendar cal = new BuddhistCalendar(new Date());
\r
242 errln("could not create BuddhistCalendar with Date");
\r
247 // new BuddhistCalendar(int year, int month, int date)
\r
248 BuddhistCalendar cal = new BuddhistCalendar(2543, Calendar.MAY, 22);
\r
250 errln("could not create BuddhistCalendar with year,month,data");
\r
255 // new BuddhistCalendar(int year, int month, int date, int hour, int minute, int second)
\r
256 BuddhistCalendar cal = new BuddhistCalendar(2543, Calendar.MAY, 22, 1, 1, 1);
\r
258 errln("could not create BuddhistCalendar with year,month,date,hour,minute,second");
\r
264 BuddhistCalendar cal = new BuddhistCalendar(2543, Calendar.MAY, 22);
\r
265 Date time = cal.getTime();
\r
267 String[] calendarLocales = {
\r
271 String[] formatLocales = {
\r
272 "en", "ar", "hu", "th"
\r
275 for (int i = 0; i < calendarLocales.length; ++i) {
\r
276 String calLocName = calendarLocales[i];
\r
277 Locale calLocale = LocaleUtility.getLocaleFromName(calLocName);
\r
278 cal = new BuddhistCalendar(calLocale);
\r
280 for (int j = 0; j < formatLocales.length; ++j) {
\r
281 String locName = formatLocales[j];
\r
282 Locale formatLocale = LocaleUtility.getLocaleFromName(locName);
\r
283 DateFormat format = DateFormat.getDateTimeInstance(cal, DateFormat.FULL, DateFormat.FULL, formatLocale);
\r
284 logln(calLocName + "/" + locName + " --> " + format.format(time));
\r
291 * Test limits of the Buddhist calendar.
\r
293 public void TestBuddhistLimits() {
\r
294 // Final parameter is either number of days, if > 0, or test
\r
295 // duration in seconds, if < 0.
\r
296 Calendar cal = Calendar.getInstance();
\r
297 cal.set(2007, Calendar.JANUARY, 1);
\r
298 BuddhistCalendar buddhist = new BuddhistCalendar();
\r
299 doLimitsTest(buddhist, null, cal.getTime());
\r
300 doTheoreticalLimitsTest(buddhist, false);
\r
304 * Default calendar for Thai (Ticket#6302)
\r
306 public void TestThaiDefault() {
\r
307 // Buddhist calendar is used as the default calendar for
\r
309 Calendar cal = Calendar.getInstance(new ULocale("th_TH"));
\r
310 String type = cal.getType();
\r
311 if (!type.equals("buddhist")) {
\r
312 errln("FAIL: Buddhist calendar is not returned for locale " + cal.toString());
\r
317 * Verify that TaiwanCalendar shifts years to Minguo Era but otherwise
\r
318 * behaves like GregorianCalendar.
\r
320 public void TestTaiwan() {
\r
321 quasiGregorianTest(new TaiwanCalendar(),
\r
323 TaiwanCalendar.BEFORE_MINGUO, 8, 1904, Calendar.FEBRUARY, 29,
\r
324 TaiwanCalendar.MINGUO, 1, 1912, Calendar.JUNE, 4,
\r
325 TaiwanCalendar.MINGUO, 3, 1914, Calendar.FEBRUARY, 12,
\r
326 TaiwanCalendar.MINGUO, 96,2007, Calendar.FEBRUARY, 12,
\r
331 * Test limits of the Taiwan calendar.
\r
333 public void TestTaiwanLimits() {
\r
334 // Final parameter is either number of days, if > 0, or test
\r
335 // duration in seconds, if < 0.
\r
336 Calendar cal = Calendar.getInstance();
\r
337 cal.set(2007, Calendar.JANUARY, 1);
\r
338 TaiwanCalendar taiwan = new TaiwanCalendar();
\r
339 doLimitsTest(taiwan, null, cal.getTime());
\r
340 doTheoreticalLimitsTest(taiwan, false);
\r
343 public void TestTaiwanCoverage() {
\r
345 // new TaiwanCalendar(ULocale)
\r
346 TaiwanCalendar cal = new TaiwanCalendar(ULocale.getDefault());
\r
348 errln("could not create TaiwanCalendar with ULocale");
\r
353 // new TaiwanCalendar(TimeZone,ULocale)
\r
354 TaiwanCalendar cal = new TaiwanCalendar(TimeZone.getDefault(),ULocale.getDefault());
\r
356 errln("could not create TaiwanCalendar with TimeZone ULocale");
\r
361 // new TaiwanCalendar(TimeZone)
\r
362 TaiwanCalendar cal = new TaiwanCalendar(TimeZone.getDefault());
\r
364 errln("could not create TaiwanCalendar with TimeZone");
\r
369 // new TaiwanCalendar(Locale)
\r
370 TaiwanCalendar cal = new TaiwanCalendar(Locale.getDefault());
\r
372 errln("could not create TaiwanCalendar with Locale");
\r
377 // new TaiwanCalendar(TimeZone, Locale)
\r
378 TaiwanCalendar cal = new TaiwanCalendar(TimeZone.getDefault(), Locale.getDefault());
\r
380 errln("could not create TaiwanCalendar with TimeZone and Locale");
\r
385 // new TaiwanCalendar(Date)
\r
386 TaiwanCalendar cal = new TaiwanCalendar(new Date());
\r
388 errln("could not create TaiwanCalendar with Date");
\r
393 // new TaiwanCalendar(int year, int month, int date)
\r
394 TaiwanCalendar cal = new TaiwanCalendar(34, Calendar.MAY, 22);
\r
396 errln("could not create TaiwanCalendar with year,month,data");
\r
401 // new TaiwanCalendar(int year, int month, int date, int hour, int minute, int second)
\r
402 TaiwanCalendar cal = new TaiwanCalendar(34, Calendar.MAY, 22, 1, 1, 1);
\r
404 errln("could not create TaiwanCalendar with year,month,date,hour,minute,second");
\r
410 TaiwanCalendar cal = new TaiwanCalendar(34, Calendar.MAY, 22);
\r
411 Date time = cal.getTime();
\r
413 String[] calendarLocales = {
\r
417 String[] formatLocales = {
\r
418 "en", "ar", "hu", "th"
\r
421 for (int i = 0; i < calendarLocales.length; ++i) {
\r
422 String calLocName = calendarLocales[i];
\r
423 Locale calLocale = LocaleUtility.getLocaleFromName(calLocName);
\r
424 cal = new TaiwanCalendar(calLocale);
\r
426 for (int j = 0; j < formatLocales.length; ++j) {
\r
427 String locName = formatLocales[j];
\r
428 Locale formatLocale = LocaleUtility.getLocaleFromName(locName);
\r
429 DateFormat format = DateFormat.getDateTimeInstance(cal, DateFormat.FULL, DateFormat.FULL, formatLocale);
\r
430 logln(calLocName + "/" + locName + " --> " + format.format(time));
\r
437 * Verify that JapaneseCalendar shifts years to Japanese Eras but otherwise
\r
438 * behaves like GregorianCalendar.
\r
440 public void TestJapanese() {
\r
441 // First make sure this test works for GregorianCalendar
\r
443 GregorianCalendar.AD, 1868, 1868, Calendar.SEPTEMBER, 8,
\r
444 GregorianCalendar.AD, 1868, 1868, Calendar.SEPTEMBER, 9,
\r
445 GregorianCalendar.AD, 1869, 1869, Calendar.JUNE, 4,
\r
446 GregorianCalendar.AD, 1912, 1912, Calendar.JULY, 29,
\r
447 GregorianCalendar.AD, 1912, 1912, Calendar.JULY, 30,
\r
448 GregorianCalendar.AD, 1912, 1912, Calendar.AUGUST, 1,
\r
450 quasiGregorianTest(new GregorianCalendar(), control);
\r
453 JapaneseCalendar.MEIJI, 1, 1868, Calendar.SEPTEMBER, 8,
\r
454 JapaneseCalendar.MEIJI, 1, 1868, Calendar.SEPTEMBER, 9,
\r
455 JapaneseCalendar.MEIJI, 2, 1869, Calendar.JUNE, 4,
\r
456 JapaneseCalendar.MEIJI, 45, 1912, Calendar.JULY, 29,
\r
457 JapaneseCalendar.TAISHO, 1, 1912, Calendar.JULY, 30,
\r
458 JapaneseCalendar.TAISHO, 1, 1912, Calendar.AUGUST, 1,
\r
460 quasiGregorianTest(new JapaneseCalendar(), data);
\r
464 * Test limits of the Gregorian calendar.
\r
466 public void TestGregorianLimits() {
\r
467 // Final parameter is either number of days, if > 0, or test
\r
468 // duration in seconds, if < 0.
\r
469 Calendar cal = Calendar.getInstance();
\r
470 cal.set(2004, Calendar.JANUARY, 1);
\r
471 GregorianCalendar gregorian = new GregorianCalendar();
\r
472 doLimitsTest(gregorian, null, cal.getTime());
\r
473 doTheoreticalLimitsTest(gregorian, false);
\r
477 * Test behavior of fieldDifference around leap years. Also test a large
\r
478 * field difference to check binary search.
\r
480 public void TestLeapFieldDifference() {
\r
481 Calendar cal = Calendar.getInstance();
\r
482 cal.set(2004, Calendar.FEBRUARY, 29);
\r
483 Date date2004 = cal.getTime();
\r
484 cal.set(2000, Calendar.FEBRUARY, 29);
\r
485 Date date2000 = cal.getTime();
\r
486 int y = cal.fieldDifference(date2004, Calendar.YEAR);
\r
487 int d = cal.fieldDifference(date2004, Calendar.DAY_OF_YEAR);
\r
489 logln("Ok: 2004/Feb/29 - 2000/Feb/29 = " + y + " years, " + d + " days");
\r
491 errln("FAIL: 2004/Feb/29 - 2000/Feb/29 = " + y + " years, " + d + " days");
\r
493 cal.setTime(date2004);
\r
494 y = cal.fieldDifference(date2000, Calendar.YEAR);
\r
495 d = cal.fieldDifference(date2000, Calendar.DAY_OF_YEAR);
\r
497 logln("Ok: 2000/Feb/29 - 2004/Feb/29 = " + y + " years, " + d + " days");
\r
499 errln("FAIL: 2000/Feb/29 - 2004/Feb/29 = " + y + " years, " + d + " days");
\r
501 // Test large difference
\r
502 cal.set(2001, Calendar.APRIL, 5); // 2452005
\r
503 Date ayl = cal.getTime();
\r
504 cal.set(1964, Calendar.SEPTEMBER, 7); // 2438646
\r
505 Date asl = cal.getTime();
\r
506 d = cal.fieldDifference(ayl, Calendar.DAY_OF_MONTH);
\r
508 int d2 = cal.fieldDifference(asl, Calendar.DAY_OF_MONTH);
\r
509 if (d == -d2 && d == 13359) {
\r
510 logln("Ok: large field difference symmetrical " + d);
\r
512 logln("FAIL: large field difference incorrect " + d + ", " + d2 +
\r
513 ", expect +/- 13359");
\r
518 * Test ms_MY "Malay (Malaysia)" locale. Bug 1543.
\r
520 public void TestMalaysianInstance() {
\r
521 Locale loc = new Locale("ms", "MY"); // Malay (Malaysia)
\r
522 Calendar cal = Calendar.getInstance(loc);
\r
524 errln("could not create Malaysian instance");
\r
529 * setFirstDayOfWeek and setMinimalDaysInFirstWeek may change the
\r
530 * field <=> time mapping, since they affect the interpretation of
\r
531 * the WEEK_OF_MONTH or WEEK_OF_YEAR fields.
\r
533 public void TestWeekShift() {
\r
534 Calendar cal = new GregorianCalendar(
\r
535 TimeZone.getTimeZone("America/Los_Angeles"),
\r
536 new Locale("en", "US"));
\r
537 cal.setTime(new Date(997257600000L)); // Wed Aug 08 01:00:00 PDT 2001
\r
538 // In pass one, change the first day of week so that the weeks
\r
539 // shift in August 2001. In pass two, change the minimal days
\r
540 // in the first week so that the weeks shift in August 2001.
\r
542 // Su Mo Tu We Th Fr Sa
\r
545 // 12 13 14 15 16 17 18
\r
546 // 19 20 21 22 23 24 25
\r
547 // 26 27 28 29 30 31
\r
548 for (int pass=0; pass<2; ++pass) {
\r
550 cal.setFirstDayOfWeek(Calendar.WEDNESDAY);
\r
551 cal.setMinimalDaysInFirstWeek(4);
\r
553 cal.setFirstDayOfWeek(Calendar.SUNDAY);
\r
554 cal.setMinimalDaysInFirstWeek(4);
\r
556 cal.add(Calendar.DATE, 1); // Force recalc
\r
557 cal.add(Calendar.DATE, -1);
\r
559 Date time1 = cal.getTime(); // Get time -- should not change
\r
561 // Now change a week parameter and then force a recalc.
\r
562 // The bug is that the recalc should not be necessary --
\r
563 // calendar should do so automatically.
\r
565 cal.setFirstDayOfWeek(Calendar.THURSDAY);
\r
567 cal.setMinimalDaysInFirstWeek(5);
\r
570 int woy1 = cal.get(Calendar.WEEK_OF_YEAR);
\r
571 int wom1 = cal.get(Calendar.WEEK_OF_MONTH);
\r
573 cal.add(Calendar.DATE, 1); // Force recalc
\r
574 cal.add(Calendar.DATE, -1);
\r
576 int woy2 = cal.get(Calendar.WEEK_OF_YEAR);
\r
577 int wom2 = cal.get(Calendar.WEEK_OF_MONTH);
\r
579 Date time2 = cal.getTime();
\r
581 if (!time1.equals(time2)) {
\r
582 errln("FAIL: shifting week should not alter time");
\r
584 logln(time1.toString());
\r
586 if (woy1 == woy2 && wom1 == wom2) {
\r
587 logln("Ok: WEEK_OF_YEAR: " + woy1 +
\r
588 ", WEEK_OF_MONTH: " + wom1);
\r
590 errln("FAIL: WEEK_OF_YEAR: " + woy1 + " => " + woy2 +
\r
591 ", WEEK_OF_MONTH: " + wom1 + " => " + wom2 +
\r
592 " after week shift");
\r
598 * Make sure that when adding a day, we actually wind up in a
\r
599 * different day. The DST adjustments we use to keep the hour
\r
600 * constant across DST changes can backfire and change the day.
\r
602 public void TestTimeZoneTransitionAdd() {
\r
603 Locale locale = Locale.US; // could also be CHINA
\r
604 SimpleDateFormat dateFormat =
\r
605 new SimpleDateFormat("MM/dd/yyyy HH:mm z", locale);
\r
607 String tz[] = TimeZone.getAvailableIDs();
\r
609 for (int z=0; z<tz.length; ++z) {
\r
610 TimeZone t = TimeZone.getTimeZone(tz[z]);
\r
611 dateFormat.setTimeZone(t);
\r
613 Calendar cal = Calendar.getInstance(t, locale);
\r
615 // Scan the year 2003, overlapping the edges of the year
\r
616 cal.set(Calendar.YEAR, 2002);
\r
617 cal.set(Calendar.MONTH, Calendar.DECEMBER);
\r
618 cal.set(Calendar.DAY_OF_MONTH, 25);
\r
620 for (int i=0; i<365+10; ++i) {
\r
621 Date yesterday = cal.getTime();
\r
622 int yesterday_day = cal.get(Calendar.DAY_OF_MONTH);
\r
623 cal.add(Calendar.DAY_OF_MONTH, 1);
\r
624 if (yesterday_day == cal.get(Calendar.DAY_OF_MONTH)) {
\r
625 errln(tz[z] + " " +
\r
626 dateFormat.format(yesterday) + " +1d= " +
\r
627 dateFormat.format(cal.getTime()));
\r
633 public void TestJB1684() {
\r
645 public TestData(int year, int month, int date,
\r
646 int womyear, int wommon, int wom, int dow,
\r
647 String data, String normalized) {
\r
649 this.month = month-1;
\r
651 this.womyear = womyear;
\r
652 this.wommon = wommon-1;
\r
655 this.data = data; // year, month, week of month, day
\r
656 this.normalized = data;
\r
657 if (normalized != null) this.normalized = normalized;
\r
661 // July 2001 August 2001 January 2002
\r
662 // Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
\r
663 // 1 2 3 4 5 6 7 1 2 3 4 1 2 3 4 5
\r
664 // 8 9 10 11 12 13 14 5 6 7 8 9 10 11 6 7 8 9 10 11 12
\r
665 // 15 16 17 18 19 20 21 12 13 14 15 16 17 18 13 14 15 16 17 18 19
\r
666 // 22 23 24 25 26 27 28 19 20 21 22 23 24 25 20 21 22 23 24 25 26
\r
667 // 29 30 31 26 27 28 29 30 31 27 28 29 30 31
\r
668 TestData[] tests = {
\r
669 new TestData(2001, 8, 6, 2001,8,2,Calendar.MONDAY, "2001 08 02 Mon", null),
\r
670 new TestData(2001, 8, 7, 2001,8,2,Calendar.TUESDAY, "2001 08 02 Tue", null),
\r
671 new TestData(2001, 8, 5,/*12,*/ 2001,8,2,Calendar.SUNDAY, "2001 08 02 Sun", null),
\r
672 new TestData(2001, 8,6, /*7, 30,*/ 2001,7,6,Calendar.MONDAY, "2001 07 06 Mon", "2001 08 02 Mon"),
\r
673 new TestData(2001, 8,7, /*7, 31,*/ 2001,7,6,Calendar.TUESDAY, "2001 07 06 Tue", "2001 08 02 Tue"),
\r
674 new TestData(2001, 8, 5, 2001,7,6,Calendar.SUNDAY, "2001 07 06 Sun", "2001 08 02 Sun"),
\r
675 new TestData(2001, 7, 30, 2001,8,1,Calendar.MONDAY, "2001 08 01 Mon", "2001 07 05 Mon"),
\r
676 new TestData(2001, 7, 31, 2001,8,1,Calendar.TUESDAY, "2001 08 01 Tue", "2001 07 05 Tue"),
\r
677 new TestData(2001, 7,29, /*8, 5,*/ 2001,8,1,Calendar.SUNDAY, "2001 08 01 Sun", "2001 07 05 Sun"),
\r
678 new TestData(2001, 12, 31, 2001,12,6,Calendar.MONDAY, "2001 12 06 Mon", null),
\r
679 new TestData(2002, 1, 1, 2002,1,1,Calendar.TUESDAY, "2002 01 01 Tue", null),
\r
680 new TestData(2002, 1, 2, 2002,1,1,Calendar.WEDNESDAY, "2002 01 01 Wed", null),
\r
681 new TestData(2002, 1, 3, 2002,1,1,Calendar.THURSDAY, "2002 01 01 Thu", null),
\r
682 new TestData(2002, 1, 4, 2002,1,1,Calendar.FRIDAY, "2002 01 01 Fri", null),
\r
683 new TestData(2002, 1, 5, 2002,1,1,Calendar.SATURDAY, "2002 01 01 Sat", null),
\r
684 new TestData(2001,12,30, /*2002, 1, 6,*/ 2002,1,1,Calendar.SUNDAY, "2002 01 01 Sun", "2001 12 06 Sun"),
\r
687 int pass = 0, error = 0, warning = 0;
\r
689 final String pattern = "yyyy MM WW EEE";
\r
690 GregorianCalendar cal = new GregorianCalendar();
\r
691 SimpleDateFormat sdf = new SimpleDateFormat(pattern);
\r
692 sdf.setCalendar(cal);
\r
694 cal.setFirstDayOfWeek(Calendar.SUNDAY);
\r
695 cal.setMinimalDaysInFirstWeek(1);
\r
697 for (int i = 0; i < tests.length; ++i) {
\r
698 TestData test = tests[i];
\r
699 log("\n-----\nTesting round trip of " + test.year +
\r
700 " " + (test.month + 1) +
\r
702 " (written as) " + test.data);
\r
705 cal.set(test.year, test.month, test.date);
\r
706 Date ms = cal.getTime();
\r
709 cal.set(Calendar.YEAR, test.womyear);
\r
710 cal.set(Calendar.MONTH, test.wommon);
\r
711 cal.set(Calendar.WEEK_OF_MONTH, test.wom);
\r
712 cal.set(Calendar.DAY_OF_WEEK, test.dow);
\r
713 Date ms2 = cal.getTime();
\r
715 if (!ms2.equals(ms)) {
\r
716 log("\nError: GregorianCalendar.DOM gave " + ms +
\r
717 "\n GregorianCalendar.WOM gave " + ms2);
\r
725 ms2 = sdf.parse(test.data);
\r
727 catch (ParseException e) {
\r
728 errln("parse exception: " + e);
\r
731 if (!ms2.equals(ms)) {
\r
732 log("\nError: GregorianCalendar gave " + ms +
\r
733 "\n SimpleDateFormat.parse gave " + ms2);
\r
739 String result = sdf.format(ms);
\r
740 if (!result.equals(test.normalized)) {
\r
741 log("\nWarning: format of '" + test.data + "' gave" +
\r
742 "\n '" + result + "'" +
\r
743 "\n expected '" + test.normalized + "'");
\r
751 ms3 = sdf.parse(result);
\r
753 catch (ParseException e) {
\r
754 errln("parse exception 2: " + e);
\r
757 if (!ms3.equals(ms)) {
\r
759 log("\nError: Re-parse of '" + result + "' gave time of " +
\r
766 String info = "\nPassed: " + pass + ", Warnings: " + warning + ", Errors: " + error;
\r
775 * Test the ZoneMeta API.
\r
777 public void TestZoneMeta() {
\r
778 // Test index by country API
\r
780 // Format: {country, zone1, zone2, ..., zoneN}
\r
781 String COUNTRY[][] = { {""},
\r
782 {"US", "America/Los_Angeles", "PST"} };
\r
783 StringBuffer buf = new StringBuffer();
\r
784 for (int i=0; i<COUNTRY.length; ++i) {
\r
785 String[] a = ZoneMeta.getAvailableIDs(COUNTRY[i][0]);
\r
787 buf.append("Country \"" + COUNTRY[i][0] + "\": [");
\r
788 // Use bitmask to track which of the expected zones we see
\r
790 for (int j=0; j<a.length; ++j) {
\r
791 if (j!=0) buf.append(", ");
\r
793 for (int k=1; k<COUNTRY[i].length; ++k) {
\r
794 if ((mask & (1<<k)) == 0 &&
\r
795 a[j].equals(COUNTRY[i][k])) {
\r
802 // Check bitmask to see if we saw all expected zones
\r
803 if (mask == (1 << (COUNTRY[i].length-1))-1) {
\r
804 logln(buf.toString());
\r
806 errln(buf.toString());
\r
810 // Test equivalent IDs API
\r
812 int n = ZoneMeta.countEquivalentIDs("PST");
\r
813 boolean ok = false;
\r
815 buf.append("Equivalent to PST: ");
\r
816 for (int i=0; i<n; ++i) {
\r
817 String id = ZoneMeta.getEquivalentID("PST", i);
\r
818 if (id.equals("America/Los_Angeles")) {
\r
821 if (i!=0) buf.append(", ");
\r
825 logln(buf.toString());
\r
827 errln(buf.toString());
\r
831 public void TestComparable() {
\r
832 GregorianCalendar c0 = new GregorianCalendar();
\r
833 GregorianCalendar c1 = new GregorianCalendar();
\r
834 c1.add(Calendar.DAY_OF_MONTH, 1);
\r
835 if (c0.compareTo(c1) >= 0) {
\r
836 errln("calendar " + c0 + " not < " + c1);
\r
838 c0.add(Calendar.MONTH, 1);
\r
839 if (c0.compareTo(c1) <= 0) {
\r
840 errln("calendar " + c0 + " not > " + c1);
\r
843 c0.setTimeInMillis(c1.getTimeInMillis());
\r
844 if (c0.compareTo(c1) != 0) {
\r
845 errln("calendar " + c0 + " not == " + c1);
\r
850 c0.compareTo((Object)null);
\r
851 errln("calendar.compareTo didn't object to null arg");
\r
853 catch (NullPointerException npe) {
\r
854 logln("PASS: calendar.compareTo objected to null arg");
\r
859 * Miscellaneous tests to increase coverage.
\r
861 public void TestCoverage() {
\r
862 // BuddhistCalendar
\r
863 BuddhistCalendar bcal = new BuddhistCalendar();
\r
864 /*int i =*/ bcal.getMinimum(Calendar.ERA);
\r
865 bcal.add(Calendar.YEAR, 1);
\r
866 bcal.add(Calendar.MONTH, 1);
\r
867 /*Date d = */bcal.getTime();
\r
869 // CalendarAstronomer
\r
870 // (This class should probably be made package-private.)
\r
871 CalendarAstronomer astro = new CalendarAstronomer();
\r
872 /*String s = */astro.local(0);
\r
875 ChineseCalendar ccal = new ChineseCalendar(TimeZone.getDefault(),
\r
876 Locale.getDefault());
\r
877 ccal.add(Calendar.MONTH, 1);
\r
878 ccal.add(Calendar.YEAR, 1);
\r
879 ccal.roll(Calendar.MONTH, 1);
\r
880 ccal.roll(Calendar.YEAR, 1);
\r
884 Calendar cal = Calendar.getInstance(Locale.US);
\r
885 logln(cal.toString());
\r
886 logln(cal.getDisplayName(Locale.US));
\r
887 int weekendOnset=-1;
\r
888 int weekendCease=-1;
\r
889 for (int i=Calendar.SUNDAY; i<=Calendar.SATURDAY; ++i) {
\r
890 if (cal.getDayOfWeekType(i) == Calendar.WEEKEND_ONSET) {
\r
893 if (cal.getDayOfWeekType(i) == Calendar.WEEKEND_CEASE) {
\r
897 // can't call this unless we get a transition day (unusual),
\r
898 // but make the call anyway for coverage reasons
\r
900 /*int x=*/ cal.getWeekendTransition(weekendOnset);
\r
901 /*int x=*/ cal.getWeekendTransition(weekendCease);
\r
902 } catch (IllegalArgumentException e) {}
\r
903 /*int x=*/ cal.isWeekend(new Date());
\r
905 // new GregorianCalendar(ULocale)
\r
906 GregorianCalendar gcal = new GregorianCalendar(ULocale.getDefault());
\r
908 errln("could not create GregorianCalendar with ULocale");
\r
910 logln("Calendar display name: " + gcal.getDisplayName(ULocale.getDefault()));
\r
913 //cover getAvailableULocales
\r
914 final ULocale[] locales = Calendar.getAvailableULocales();
\r
915 long count = locales.length;
\r
917 errln("getAvailableULocales return empty list");
\r
918 logln("" + count + " available ulocales in Calendar.");
\r
920 // Jitterbug 4451, for coverage
\r
921 class StubCalendar extends Calendar{
\r
923 * For serialization
\r
925 private static final long serialVersionUID = -4558903444622684759L;
\r
926 protected int handleGetLimit(int field, int limitType) {return 0;}
\r
927 protected int handleComputeMonthStart(int eyear, int month, boolean useMonth) {return 0;}
\r
928 protected int handleGetExtendedYear() {return 0;}
\r
930 if (Calendar.gregorianPreviousMonthLength(2000,2) != 29){
\r
931 errln("Year 2000 Feb should have 29 days.");
\r
933 long millis = Calendar.julianDayToMillis(Calendar.MAX_JULIAN);
\r
934 if(millis != Calendar.MAX_MILLIS){
\r
935 errln("Did not get the expected value from julianDayToMillis. Got:" + millis);
\r
937 DateFormat df = handleGetDateFormat("",Locale.getDefault());
\r
938 if (!df.equals(handleGetDateFormat("",ULocale.getDefault()))){
\r
939 errln ("Calendar.handleGetDateFormat(String, Locale) should delegate to ( ,ULocale)");
\r
941 if (!getType().equals("gregorian")){
\r
942 errln ("Calendar.getType() should be 'gregorian'");
\r
946 StubCalendar stub = new StubCalendar();
\r
950 // Tests for jb 4541
\r
951 public void TestJB4541() {
\r
952 ULocale loc = new ULocale("en_US");
\r
954 // !!! Shouldn't we have an api like this?
\r
955 // !!! Question: should this reflect those actually available in this copy of ICU, or
\r
956 // the list of types we assume is available?
\r
957 // String[] calTypes = Calendar.getAvailableTypes();
\r
958 final String[] calTypes = {
\r
959 "buddhist", "chinese", "coptic", "ethiopic", "gregorian", "hebrew",
\r
960 "islamic", "islamic-civil", "japanese", "roc"
\r
963 // constructing a DateFormat with a locale indicating a calendar type should construct a
\r
964 // date format appropriate to that calendar
\r
965 final Date time = new Date();
\r
966 for (int i = 0; i < calTypes.length; ++i) {
\r
967 ULocale aLoc = loc.setKeywordValue("calendar", calTypes[i]);
\r
968 logln("locale: " + aLoc);
\r
970 DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL,
\r
974 logln("df type: " + df.getClass().getName() + " loc: " + df.getLocale(ULocale.VALID_LOCALE));
\r
976 Calendar cal = df.getCalendar();
\r
977 // todo, what about variants of calendars, we have a type for islamic-civil, should we also have a type
\r
978 // for variants of other calendars?
\r
979 assertEquals("calendar types", cal.getType(), calTypes[i].equals("islamic-civil") ? "islamic" : calTypes[i]);
\r
980 DateFormat df2 = cal.getDateTimeFormat(DateFormat.FULL, DateFormat.FULL, ULocale.US);
\r
981 logln("df2 type: " + df2.getClass().getName() + " loc: " + df2.getLocale(ULocale.VALID_LOCALE));
\r
982 assertEquals("format results", df.format(time), df2.format(time));
\r
985 // dateFormat.setCalendar should throw exception if wrong format for calendar
\r
987 DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL,
\r
989 new ULocale("en_US@calendar=chinese"));
\r
991 logln("dateformat type: " + df.getClass().getName());
\r
993 Calendar cal = Calendar.getInstance(new ULocale("en_US@calendar=chinese"));
\r
995 logln("calendar type: " + cal.getClass().getName());
\r
999 public void TestTypes() {
\r
1001 "en_US_VALLEYGIRL",
\r
1002 "en_US_VALLEYGIRL@collation=phonebook;calendar=japanese",
\r
1003 "en_US_VALLEYGIRL@collation=phonebook;calendar=gregorian",
\r
1004 "ja_JP@calendar=japanese",
\r
1005 "th_TH@calendar=buddhist",
\r
1006 "ja_JP_TRADITIONAL",
\r
1007 "th_TH_TRADITIONAL",
\r
1008 "th_TH_TRADITIONAL@calendar=gregorian",
\r
1010 "th_TH", // Default calendar for th_TH is buddhist
\r
1011 "th", // th's default region is TH and buddhist is used as default for TH
\r
1012 // FIXME: ICU Service canonicalize en_TH to en, so TH is ignored in Calendar instantiation. See #6816.
\r
1013 // "en_TH", // Default calendar for any locales with region TH is buddhist
\r
1016 String[] types = {
\r
1028 // FIXME: ICU Service canonicalize en_TH to en, so TH is ignored in Calendar instantiation. See #6816.
\r
1032 for (int i = 0; i < locs.length; i++) {
\r
1033 Calendar cal = Calendar.getInstance(new ULocale(locs[i]));
\r
1034 if (!cal.getType().equals(types[i])) {
\r
1035 errln(locs[i] + " Calendar type " + cal.getType() + " instead of " + types[i]);
\r