2 *******************************************************************************
\r
3 * Copyright (C) 2000-2010, 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.text.ParseException;
\r
10 import java.util.Date;
\r
11 import java.util.Locale;
\r
13 import com.ibm.icu.impl.CalendarAstronomer;
\r
14 import com.ibm.icu.impl.LocaleUtility;
\r
15 import com.ibm.icu.impl.ZoneMeta;
\r
16 import com.ibm.icu.text.DateFormat;
\r
17 import com.ibm.icu.text.SimpleDateFormat;
\r
18 import com.ibm.icu.util.BuddhistCalendar;
\r
19 import com.ibm.icu.util.Calendar;
\r
20 import com.ibm.icu.util.ChineseCalendar;
\r
21 import com.ibm.icu.util.GregorianCalendar;
\r
22 import com.ibm.icu.util.JapaneseCalendar;
\r
23 import com.ibm.icu.util.TaiwanCalendar;
\r
24 import com.ibm.icu.util.TimeZone;
\r
25 import com.ibm.icu.util.ULocale;
\r
28 * @summary Tests of new functionality in IBMCalendar
\r
30 public class IBMCalendarTest extends CalendarTest {
\r
32 public static void main(String[] args) throws Exception {
\r
33 new IBMCalendarTest().run(args);
\r
37 * Test weekend support in IBMCalendar.
\r
39 * NOTE: This test will have to be updated when the isWeekend() etc.
\r
40 * API is finalized later.
\r
42 * In particular, the test will have to be rewritten to instantiate
\r
43 * a Calendar in the given locale (using getInstance()) and call
\r
44 * that Calendar's isWeekend() etc. methods.
\r
46 public void TestWeekend() {
\r
47 SimpleDateFormat fmt = new SimpleDateFormat("EEE MMM dd yyyy G HH:mm:ss.SSS");
\r
50 // This test tests for specific locale data. This is probably okay
\r
51 // as far as US data is concerned, but if the Arabic/Yemen data
\r
52 // changes, this test will have to be updated.
\r
54 // Test specific days
\r
56 Locale.US, new int[] { // Saturday:Sunday
\r
57 2000, Calendar.MARCH, 17, 23, 0, 0, // Fri 23:00
\r
58 2000, Calendar.MARCH, 18, 0, -1, 0, // Fri 23:59:59.999
\r
59 2000, Calendar.MARCH, 18, 0, 0, 1, // Sat 00:00
\r
60 2000, Calendar.MARCH, 18, 15, 0, 1, // Sat 15:00
\r
61 2000, Calendar.MARCH, 19, 23, 0, 1, // Sun 23:00
\r
62 2000, Calendar.MARCH, 20, 0, -1, 1, // Sun 23:59:59.999
\r
63 2000, Calendar.MARCH, 20, 0, 0, 0, // Mon 00:00
\r
64 2000, Calendar.MARCH, 20, 8, 0, 0, // Mon 08:00
\r
66 new Locale("ar", "YE"), new int[] { // Thursday:Friday
\r
67 2000, Calendar.MARCH, 15, 23, 0, 0, // Wed 23:00
\r
68 2000, Calendar.MARCH, 16, 0, -1, 0, // Wed 23:59:59.999
\r
69 2000, Calendar.MARCH, 16, 0, 0, 1, // Thu 00:00
\r
70 2000, Calendar.MARCH, 16, 15, 0, 1, // Thu 15:00
\r
71 2000, Calendar.MARCH, 17, 23, 0, 1, // Fri 23:00
\r
72 2000, Calendar.MARCH, 18, 0, -1, 1, // Fri 23:59:59.999
\r
73 2000, Calendar.MARCH, 18, 0, 0, 0, // Sat 00:00
\r
74 2000, Calendar.MARCH, 18, 8, 0, 0, // Sat 08:00
\r
78 // Test days of the week
\r
80 Locale.US, new int[] {
\r
81 Calendar.MONDAY, Calendar.WEEKDAY,
\r
82 Calendar.FRIDAY, Calendar.WEEKDAY,
\r
83 Calendar.SATURDAY, Calendar.WEEKEND,
\r
84 Calendar.SUNDAY, Calendar.WEEKEND_CEASE,
\r
86 new Locale("ar", "YE"), new int[] { // Thursday:Friday
\r
87 Calendar.WEDNESDAY,Calendar.WEEKDAY,
\r
88 Calendar.SATURDAY, Calendar.WEEKDAY,
\r
89 Calendar.THURSDAY, Calendar.WEEKEND,
\r
90 Calendar.FRIDAY, Calendar.WEEKEND_CEASE,
\r
94 // We only test the getDayOfWeekType() and isWeekend() APIs.
\r
95 // The getWeekendTransition() API is tested indirectly via the
\r
96 // isWeekend() API, which calls it.
\r
98 for (int i1=0; i1<DATA1.length; i1+=2) {
\r
99 Locale loc = (Locale)DATA1[i1];
\r
100 int[] data = (int[]) DATA1[i1+1];
\r
101 Calendar cal = Calendar.getInstance(loc);
\r
102 logln("Locale: " + loc);
\r
103 for (int i=0; i<data.length; i+=6) {
\r
105 cal.set(data[i], data[i+1], data[i+2], data[i+3], 0, 0);
\r
106 if (data[i+4] != 0) {
\r
107 cal.setTime(new Date(cal.getTime().getTime() + data[i+4]));
\r
109 boolean isWeekend = cal.isWeekend();
\r
110 boolean ok = isWeekend == (data[i+5] != 0);
\r
112 logln("Ok: " + fmt.format(cal.getTime()) + " isWeekend=" + isWeekend);
\r
114 errln("FAIL: " + fmt.format(cal.getTime()) + " isWeekend=" + isWeekend +
\r
115 ", expected=" + (!isWeekend));
\r
120 for (int i2=0; i2<DATA2.length; i2+=2) {
\r
121 Locale loc = (Locale)DATA2[i2];
\r
122 int[] data = (int[]) DATA2[i2+1];
\r
123 logln("Locale: " + loc);
\r
124 Calendar cal = Calendar.getInstance(loc);
\r
125 for (int i=0; i<data.length; i+=2) {
\r
126 int type = cal.getDayOfWeekType(data[i]);
\r
127 int exp = data[i+1];
\r
129 logln("Ok: DOW " + data[i] + " type=" + type);
\r
131 errln("FAIL: DOW " + data[i] + " type=" + type +
\r
132 ", expected=" + exp);
\r
139 * Run a test of a quasi-Gregorian calendar. This is a calendar
\r
140 * that behaves like a Gregorian but has different year/era mappings.
\r
141 * The int[] data array should have the format:
\r
143 * { era, year, gregorianYear, month, dayOfMonth, ... }
\r
145 void quasiGregorianTest(Calendar cal, int[] data) {
\r
146 // As of JDK 1.4.1_01, using the Sun JDK GregorianCalendar as
\r
147 // a reference throws us off by one hour. This is most likely
\r
148 // due to the JDK 1.4 incorporation of historical time zones.
\r
149 //java.util.Calendar grego = java.util.Calendar.getInstance();
\r
150 Calendar grego = Calendar.getInstance();
\r
151 for (int i=0; i<data.length; ) {
\r
152 int era = data[i++];
\r
153 int year = data[i++];
\r
154 int gregorianYear = data[i++];
\r
155 int month = data[i++];
\r
156 int dayOfMonth = data[i++];
\r
159 grego.set(gregorianYear, month, dayOfMonth);
\r
160 Date D = grego.getTime();
\r
163 cal.set(Calendar.ERA, era);
\r
164 cal.set(year, month, dayOfMonth);
\r
165 Date d = cal.getTime();
\r
167 logln("OK: " + era + ":" + year + "/" + (month+1) + "/" + dayOfMonth +
\r
170 errln("Fail: " + era + ":" + year + "/" + (month+1) + "/" + dayOfMonth +
\r
171 " => " + d + ", expected " + D);
\r
176 int e = cal.get(Calendar.ERA);
\r
177 int y = cal.get(Calendar.YEAR);
\r
178 if (y == year && e == era) {
\r
179 logln("OK: " + D + " => " + cal.get(Calendar.ERA) + ":" +
\r
180 cal.get(Calendar.YEAR) + "/" +
\r
181 (cal.get(Calendar.MONTH)+1) + "/" + cal.get(Calendar.DATE));
\r
183 logln("Fail: " + D + " => " + cal.get(Calendar.ERA) + ":" +
\r
184 cal.get(Calendar.YEAR) + "/" +
\r
185 (cal.get(Calendar.MONTH)+1) + "/" + cal.get(Calendar.DATE) +
\r
186 ", expected " + era + ":" + year + "/" + (month+1) + "/" +
\r
193 * Verify that BuddhistCalendar shifts years to Buddhist Era but otherwise
\r
194 * behaves like GregorianCalendar.
\r
196 public void TestBuddhist() {
\r
197 quasiGregorianTest(new BuddhistCalendar(),
\r
199 // BE 2542 == 1999 CE
\r
200 0, 2542, 1999, Calendar.JUNE, 4
\r
204 public void TestBuddhistCoverage() {
\r
206 // new BuddhistCalendar(ULocale)
\r
207 BuddhistCalendar cal = new BuddhistCalendar(ULocale.getDefault());
\r
209 errln("could not create BuddhistCalendar with ULocale");
\r
214 // new BuddhistCalendar(TimeZone,ULocale)
\r
215 BuddhistCalendar cal = new BuddhistCalendar(TimeZone.getDefault(),ULocale.getDefault());
\r
217 errln("could not create BuddhistCalendar with TimeZone ULocale");
\r
222 // new BuddhistCalendar(TimeZone)
\r
223 BuddhistCalendar cal = new BuddhistCalendar(TimeZone.getDefault());
\r
225 errln("could not create BuddhistCalendar with TimeZone");
\r
230 // new BuddhistCalendar(Locale)
\r
231 BuddhistCalendar cal = new BuddhistCalendar(Locale.getDefault());
\r
233 errln("could not create BuddhistCalendar with Locale");
\r
238 // new BuddhistCalendar(TimeZone, Locale)
\r
239 BuddhistCalendar cal = new BuddhistCalendar(TimeZone.getDefault(), Locale.getDefault());
\r
241 errln("could not create BuddhistCalendar with TimeZone and Locale");
\r
246 // new BuddhistCalendar(Date)
\r
247 BuddhistCalendar cal = new BuddhistCalendar(new Date());
\r
249 errln("could not create BuddhistCalendar with Date");
\r
254 // new BuddhistCalendar(int year, int month, int date)
\r
255 BuddhistCalendar cal = new BuddhistCalendar(2543, Calendar.MAY, 22);
\r
257 errln("could not create BuddhistCalendar with year,month,data");
\r
262 // new BuddhistCalendar(int year, int month, int date, int hour, int minute, int second)
\r
263 BuddhistCalendar cal = new BuddhistCalendar(2543, Calendar.MAY, 22, 1, 1, 1);
\r
265 errln("could not create BuddhistCalendar with year,month,date,hour,minute,second");
\r
271 BuddhistCalendar cal = new BuddhistCalendar(2543, Calendar.MAY, 22);
\r
272 Date time = cal.getTime();
\r
274 String[] calendarLocales = {
\r
278 String[] formatLocales = {
\r
279 "en", "ar", "hu", "th"
\r
282 for (int i = 0; i < calendarLocales.length; ++i) {
\r
283 String calLocName = calendarLocales[i];
\r
284 Locale calLocale = LocaleUtility.getLocaleFromName(calLocName);
\r
285 cal = new BuddhistCalendar(calLocale);
\r
287 for (int j = 0; j < formatLocales.length; ++j) {
\r
288 String locName = formatLocales[j];
\r
289 Locale formatLocale = LocaleUtility.getLocaleFromName(locName);
\r
290 DateFormat format = DateFormat.getDateTimeInstance(cal, DateFormat.FULL, DateFormat.FULL, formatLocale);
\r
291 logln(calLocName + "/" + locName + " --> " + format.format(time));
\r
298 * Test limits of the Buddhist calendar.
\r
300 public void TestBuddhistLimits() {
\r
301 // Final parameter is either number of days, if > 0, or test
\r
302 // duration in seconds, if < 0.
\r
303 Calendar cal = Calendar.getInstance();
\r
304 cal.set(2007, Calendar.JANUARY, 1);
\r
305 BuddhistCalendar buddhist = new BuddhistCalendar();
\r
306 doLimitsTest(buddhist, null, cal.getTime());
\r
307 doTheoreticalLimitsTest(buddhist, false);
\r
311 * Default calendar for Thai (Ticket#6302)
\r
313 public void TestThaiDefault() {
\r
314 // Buddhist calendar is used as the default calendar for
\r
316 Calendar cal = Calendar.getInstance(new ULocale("th_TH"));
\r
317 String type = cal.getType();
\r
318 if (!type.equals("buddhist")) {
\r
319 errln("FAIL: Buddhist calendar is not returned for locale " + cal.toString());
\r
324 * Verify that TaiwanCalendar shifts years to Minguo Era but otherwise
\r
325 * behaves like GregorianCalendar.
\r
327 public void TestTaiwan() {
\r
328 quasiGregorianTest(new TaiwanCalendar(),
\r
330 TaiwanCalendar.BEFORE_MINGUO, 8, 1904, Calendar.FEBRUARY, 29,
\r
331 TaiwanCalendar.MINGUO, 1, 1912, Calendar.JUNE, 4,
\r
332 TaiwanCalendar.MINGUO, 3, 1914, Calendar.FEBRUARY, 12,
\r
333 TaiwanCalendar.MINGUO, 96,2007, Calendar.FEBRUARY, 12,
\r
338 * Test limits of the Taiwan calendar.
\r
340 public void TestTaiwanLimits() {
\r
341 // Final parameter is either number of days, if > 0, or test
\r
342 // duration in seconds, if < 0.
\r
343 Calendar cal = Calendar.getInstance();
\r
344 cal.set(2007, Calendar.JANUARY, 1);
\r
345 TaiwanCalendar taiwan = new TaiwanCalendar();
\r
346 doLimitsTest(taiwan, null, cal.getTime());
\r
347 doTheoreticalLimitsTest(taiwan, false);
\r
350 public void TestTaiwanCoverage() {
\r
352 // new TaiwanCalendar(ULocale)
\r
353 TaiwanCalendar cal = new TaiwanCalendar(ULocale.getDefault());
\r
355 errln("could not create TaiwanCalendar with ULocale");
\r
360 // new TaiwanCalendar(TimeZone,ULocale)
\r
361 TaiwanCalendar cal = new TaiwanCalendar(TimeZone.getDefault(),ULocale.getDefault());
\r
363 errln("could not create TaiwanCalendar with TimeZone ULocale");
\r
368 // new TaiwanCalendar(TimeZone)
\r
369 TaiwanCalendar cal = new TaiwanCalendar(TimeZone.getDefault());
\r
371 errln("could not create TaiwanCalendar with TimeZone");
\r
376 // new TaiwanCalendar(Locale)
\r
377 TaiwanCalendar cal = new TaiwanCalendar(Locale.getDefault());
\r
379 errln("could not create TaiwanCalendar with Locale");
\r
384 // new TaiwanCalendar(TimeZone, Locale)
\r
385 TaiwanCalendar cal = new TaiwanCalendar(TimeZone.getDefault(), Locale.getDefault());
\r
387 errln("could not create TaiwanCalendar with TimeZone and Locale");
\r
392 // new TaiwanCalendar(Date)
\r
393 TaiwanCalendar cal = new TaiwanCalendar(new Date());
\r
395 errln("could not create TaiwanCalendar with Date");
\r
400 // new TaiwanCalendar(int year, int month, int date)
\r
401 TaiwanCalendar cal = new TaiwanCalendar(34, Calendar.MAY, 22);
\r
403 errln("could not create TaiwanCalendar with year,month,data");
\r
408 // new TaiwanCalendar(int year, int month, int date, int hour, int minute, int second)
\r
409 TaiwanCalendar cal = new TaiwanCalendar(34, Calendar.MAY, 22, 1, 1, 1);
\r
411 errln("could not create TaiwanCalendar with year,month,date,hour,minute,second");
\r
417 TaiwanCalendar cal = new TaiwanCalendar(34, Calendar.MAY, 22);
\r
418 Date time = cal.getTime();
\r
420 String[] calendarLocales = {
\r
424 String[] formatLocales = {
\r
425 "en", "ar", "hu", "th"
\r
428 for (int i = 0; i < calendarLocales.length; ++i) {
\r
429 String calLocName = calendarLocales[i];
\r
430 Locale calLocale = LocaleUtility.getLocaleFromName(calLocName);
\r
431 cal = new TaiwanCalendar(calLocale);
\r
433 for (int j = 0; j < formatLocales.length; ++j) {
\r
434 String locName = formatLocales[j];
\r
435 Locale formatLocale = LocaleUtility.getLocaleFromName(locName);
\r
436 DateFormat format = DateFormat.getDateTimeInstance(cal, DateFormat.FULL, DateFormat.FULL, formatLocale);
\r
437 logln(calLocName + "/" + locName + " --> " + format.format(time));
\r
444 * Verify that JapaneseCalendar shifts years to Japanese Eras but otherwise
\r
445 * behaves like GregorianCalendar.
\r
447 public void TestJapanese() {
\r
448 // First make sure this test works for GregorianCalendar
\r
450 GregorianCalendar.AD, 1868, 1868, Calendar.SEPTEMBER, 8,
\r
451 GregorianCalendar.AD, 1868, 1868, Calendar.SEPTEMBER, 9,
\r
452 GregorianCalendar.AD, 1869, 1869, Calendar.JUNE, 4,
\r
453 GregorianCalendar.AD, 1912, 1912, Calendar.JULY, 29,
\r
454 GregorianCalendar.AD, 1912, 1912, Calendar.JULY, 30,
\r
455 GregorianCalendar.AD, 1912, 1912, Calendar.AUGUST, 1,
\r
457 quasiGregorianTest(new GregorianCalendar(), control);
\r
460 JapaneseCalendar.MEIJI, 1, 1868, Calendar.SEPTEMBER, 8,
\r
461 JapaneseCalendar.MEIJI, 1, 1868, Calendar.SEPTEMBER, 9,
\r
462 JapaneseCalendar.MEIJI, 2, 1869, Calendar.JUNE, 4,
\r
463 JapaneseCalendar.MEIJI, 45, 1912, Calendar.JULY, 29,
\r
464 JapaneseCalendar.TAISHO, 1, 1912, Calendar.JULY, 30,
\r
465 JapaneseCalendar.TAISHO, 1, 1912, Calendar.AUGUST, 1,
\r
467 quasiGregorianTest(new JapaneseCalendar(), data);
\r
471 * Test limits of the Gregorian calendar.
\r
473 public void TestGregorianLimits() {
\r
474 // Final parameter is either number of days, if > 0, or test
\r
475 // duration in seconds, if < 0.
\r
476 Calendar cal = Calendar.getInstance();
\r
477 cal.set(2004, Calendar.JANUARY, 1);
\r
478 GregorianCalendar gregorian = new GregorianCalendar();
\r
479 doLimitsTest(gregorian, null, cal.getTime());
\r
480 doTheoreticalLimitsTest(gregorian, false);
\r
484 * Test behavior of fieldDifference around leap years. Also test a large
\r
485 * field difference to check binary search.
\r
487 public void TestLeapFieldDifference() {
\r
488 Calendar cal = Calendar.getInstance();
\r
489 cal.set(2004, Calendar.FEBRUARY, 29);
\r
490 Date date2004 = cal.getTime();
\r
491 cal.set(2000, Calendar.FEBRUARY, 29);
\r
492 Date date2000 = cal.getTime();
\r
493 int y = cal.fieldDifference(date2004, Calendar.YEAR);
\r
494 int d = cal.fieldDifference(date2004, Calendar.DAY_OF_YEAR);
\r
496 logln("Ok: 2004/Feb/29 - 2000/Feb/29 = " + y + " years, " + d + " days");
\r
498 errln("FAIL: 2004/Feb/29 - 2000/Feb/29 = " + y + " years, " + d + " days");
\r
500 cal.setTime(date2004);
\r
501 y = cal.fieldDifference(date2000, Calendar.YEAR);
\r
502 d = cal.fieldDifference(date2000, Calendar.DAY_OF_YEAR);
\r
504 logln("Ok: 2000/Feb/29 - 2004/Feb/29 = " + y + " years, " + d + " days");
\r
506 errln("FAIL: 2000/Feb/29 - 2004/Feb/29 = " + y + " years, " + d + " days");
\r
508 // Test large difference
\r
509 cal.set(2001, Calendar.APRIL, 5); // 2452005
\r
510 Date ayl = cal.getTime();
\r
511 cal.set(1964, Calendar.SEPTEMBER, 7); // 2438646
\r
512 Date asl = cal.getTime();
\r
513 d = cal.fieldDifference(ayl, Calendar.DAY_OF_MONTH);
\r
515 int d2 = cal.fieldDifference(asl, Calendar.DAY_OF_MONTH);
\r
516 if (d == -d2 && d == 13359) {
\r
517 logln("Ok: large field difference symmetrical " + d);
\r
519 logln("FAIL: large field difference incorrect " + d + ", " + d2 +
\r
520 ", expect +/- 13359");
\r
525 * Test ms_MY "Malay (Malaysia)" locale. Bug 1543.
\r
527 public void TestMalaysianInstance() {
\r
528 Locale loc = new Locale("ms", "MY"); // Malay (Malaysia)
\r
529 Calendar cal = Calendar.getInstance(loc);
\r
531 errln("could not create Malaysian instance");
\r
536 * setFirstDayOfWeek and setMinimalDaysInFirstWeek may change the
\r
537 * field <=> time mapping, since they affect the interpretation of
\r
538 * the WEEK_OF_MONTH or WEEK_OF_YEAR fields.
\r
540 public void TestWeekShift() {
\r
541 Calendar cal = new GregorianCalendar(
\r
542 TimeZone.getTimeZone("America/Los_Angeles"),
\r
543 new Locale("en", "US"));
\r
544 cal.setTime(new Date(997257600000L)); // Wed Aug 08 01:00:00 PDT 2001
\r
545 // In pass one, change the first day of week so that the weeks
\r
546 // shift in August 2001. In pass two, change the minimal days
\r
547 // in the first week so that the weeks shift in August 2001.
\r
549 // Su Mo Tu We Th Fr Sa
\r
552 // 12 13 14 15 16 17 18
\r
553 // 19 20 21 22 23 24 25
\r
554 // 26 27 28 29 30 31
\r
555 for (int pass=0; pass<2; ++pass) {
\r
557 cal.setFirstDayOfWeek(Calendar.WEDNESDAY);
\r
558 cal.setMinimalDaysInFirstWeek(4);
\r
560 cal.setFirstDayOfWeek(Calendar.SUNDAY);
\r
561 cal.setMinimalDaysInFirstWeek(4);
\r
563 cal.add(Calendar.DATE, 1); // Force recalc
\r
564 cal.add(Calendar.DATE, -1);
\r
566 Date time1 = cal.getTime(); // Get time -- should not change
\r
568 // Now change a week parameter and then force a recalc.
\r
569 // The bug is that the recalc should not be necessary --
\r
570 // calendar should do so automatically.
\r
572 cal.setFirstDayOfWeek(Calendar.THURSDAY);
\r
574 cal.setMinimalDaysInFirstWeek(5);
\r
577 int woy1 = cal.get(Calendar.WEEK_OF_YEAR);
\r
578 int wom1 = cal.get(Calendar.WEEK_OF_MONTH);
\r
580 cal.add(Calendar.DATE, 1); // Force recalc
\r
581 cal.add(Calendar.DATE, -1);
\r
583 int woy2 = cal.get(Calendar.WEEK_OF_YEAR);
\r
584 int wom2 = cal.get(Calendar.WEEK_OF_MONTH);
\r
586 Date time2 = cal.getTime();
\r
588 if (!time1.equals(time2)) {
\r
589 errln("FAIL: shifting week should not alter time");
\r
591 logln(time1.toString());
\r
593 if (woy1 == woy2 && wom1 == wom2) {
\r
594 logln("Ok: WEEK_OF_YEAR: " + woy1 +
\r
595 ", WEEK_OF_MONTH: " + wom1);
\r
597 errln("FAIL: WEEK_OF_YEAR: " + woy1 + " => " + woy2 +
\r
598 ", WEEK_OF_MONTH: " + wom1 + " => " + wom2 +
\r
599 " after week shift");
\r
605 * Make sure that when adding a day, we actually wind up in a
\r
606 * different day. The DST adjustments we use to keep the hour
\r
607 * constant across DST changes can backfire and change the day.
\r
609 public void TestTimeZoneTransitionAdd() {
\r
610 Locale locale = Locale.US; // could also be CHINA
\r
611 SimpleDateFormat dateFormat =
\r
612 new SimpleDateFormat("MM/dd/yyyy HH:mm z", locale);
\r
614 String tz[] = TimeZone.getAvailableIDs();
\r
616 for (int z=0; z<tz.length; ++z) {
\r
617 TimeZone t = TimeZone.getTimeZone(tz[z]);
\r
618 dateFormat.setTimeZone(t);
\r
620 Calendar cal = Calendar.getInstance(t, locale);
\r
622 // Scan the year 2003, overlapping the edges of the year
\r
623 cal.set(Calendar.YEAR, 2002);
\r
624 cal.set(Calendar.MONTH, Calendar.DECEMBER);
\r
625 cal.set(Calendar.DAY_OF_MONTH, 25);
\r
627 for (int i=0; i<365+10; ++i) {
\r
628 Date yesterday = cal.getTime();
\r
629 int yesterday_day = cal.get(Calendar.DAY_OF_MONTH);
\r
630 cal.add(Calendar.DAY_OF_MONTH, 1);
\r
631 if (yesterday_day == cal.get(Calendar.DAY_OF_MONTH)) {
\r
632 errln(tz[z] + " " +
\r
633 dateFormat.format(yesterday) + " +1d= " +
\r
634 dateFormat.format(cal.getTime()));
\r
640 public void TestJB1684() {
\r
652 public TestData(int year, int month, int date,
\r
653 int womyear, int wommon, int wom, int dow,
\r
654 String data, String normalized) {
\r
656 this.month = month-1;
\r
658 this.womyear = womyear;
\r
659 this.wommon = wommon-1;
\r
662 this.data = data; // year, month, week of month, day
\r
663 this.normalized = data;
\r
664 if (normalized != null) this.normalized = normalized;
\r
668 // July 2001 August 2001 January 2002
\r
669 // Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
\r
670 // 1 2 3 4 5 6 7 1 2 3 4 1 2 3 4 5
\r
671 // 8 9 10 11 12 13 14 5 6 7 8 9 10 11 6 7 8 9 10 11 12
\r
672 // 15 16 17 18 19 20 21 12 13 14 15 16 17 18 13 14 15 16 17 18 19
\r
673 // 22 23 24 25 26 27 28 19 20 21 22 23 24 25 20 21 22 23 24 25 26
\r
674 // 29 30 31 26 27 28 29 30 31 27 28 29 30 31
\r
675 TestData[] tests = {
\r
676 new TestData(2001, 8, 6, 2001,8,2,Calendar.MONDAY, "2001 08 02 Mon", null),
\r
677 new TestData(2001, 8, 7, 2001,8,2,Calendar.TUESDAY, "2001 08 02 Tue", null),
\r
678 new TestData(2001, 8, 5,/*12,*/ 2001,8,2,Calendar.SUNDAY, "2001 08 02 Sun", null),
\r
679 new TestData(2001, 8,6, /*7, 30,*/ 2001,7,6,Calendar.MONDAY, "2001 07 06 Mon", "2001 08 02 Mon"),
\r
680 new TestData(2001, 8,7, /*7, 31,*/ 2001,7,6,Calendar.TUESDAY, "2001 07 06 Tue", "2001 08 02 Tue"),
\r
681 new TestData(2001, 8, 5, 2001,7,6,Calendar.SUNDAY, "2001 07 06 Sun", "2001 08 02 Sun"),
\r
682 new TestData(2001, 7, 30, 2001,8,1,Calendar.MONDAY, "2001 08 01 Mon", "2001 07 05 Mon"),
\r
683 new TestData(2001, 7, 31, 2001,8,1,Calendar.TUESDAY, "2001 08 01 Tue", "2001 07 05 Tue"),
\r
684 new TestData(2001, 7,29, /*8, 5,*/ 2001,8,1,Calendar.SUNDAY, "2001 08 01 Sun", "2001 07 05 Sun"),
\r
685 new TestData(2001, 12, 31, 2001,12,6,Calendar.MONDAY, "2001 12 06 Mon", null),
\r
686 new TestData(2002, 1, 1, 2002,1,1,Calendar.TUESDAY, "2002 01 01 Tue", null),
\r
687 new TestData(2002, 1, 2, 2002,1,1,Calendar.WEDNESDAY, "2002 01 01 Wed", null),
\r
688 new TestData(2002, 1, 3, 2002,1,1,Calendar.THURSDAY, "2002 01 01 Thu", null),
\r
689 new TestData(2002, 1, 4, 2002,1,1,Calendar.FRIDAY, "2002 01 01 Fri", null),
\r
690 new TestData(2002, 1, 5, 2002,1,1,Calendar.SATURDAY, "2002 01 01 Sat", null),
\r
691 new TestData(2001,12,30, /*2002, 1, 6,*/ 2002,1,1,Calendar.SUNDAY, "2002 01 01 Sun", "2001 12 06 Sun"),
\r
694 int pass = 0, error = 0, warning = 0;
\r
696 final String pattern = "yyyy MM WW EEE";
\r
697 GregorianCalendar cal = new GregorianCalendar();
\r
698 SimpleDateFormat sdf = new SimpleDateFormat(pattern);
\r
699 sdf.setCalendar(cal);
\r
701 cal.setFirstDayOfWeek(Calendar.SUNDAY);
\r
702 cal.setMinimalDaysInFirstWeek(1);
\r
704 for (int i = 0; i < tests.length; ++i) {
\r
705 TestData test = tests[i];
\r
706 log("\n-----\nTesting round trip of " + test.year +
\r
707 " " + (test.month + 1) +
\r
709 " (written as) " + test.data);
\r
712 cal.set(test.year, test.month, test.date);
\r
713 Date ms = cal.getTime();
\r
716 cal.set(Calendar.YEAR, test.womyear);
\r
717 cal.set(Calendar.MONTH, test.wommon);
\r
718 cal.set(Calendar.WEEK_OF_MONTH, test.wom);
\r
719 cal.set(Calendar.DAY_OF_WEEK, test.dow);
\r
720 Date ms2 = cal.getTime();
\r
722 if (!ms2.equals(ms)) {
\r
723 log("\nError: GregorianCalendar.DOM gave " + ms +
\r
724 "\n GregorianCalendar.WOM gave " + ms2);
\r
732 ms2 = sdf.parse(test.data);
\r
734 catch (ParseException e) {
\r
735 errln("parse exception: " + e);
\r
738 if (!ms2.equals(ms)) {
\r
739 log("\nError: GregorianCalendar gave " + ms +
\r
740 "\n SimpleDateFormat.parse gave " + ms2);
\r
746 String result = sdf.format(ms);
\r
747 if (!result.equals(test.normalized)) {
\r
748 log("\nWarning: format of '" + test.data + "' gave" +
\r
749 "\n '" + result + "'" +
\r
750 "\n expected '" + test.normalized + "'");
\r
758 ms3 = sdf.parse(result);
\r
760 catch (ParseException e) {
\r
761 errln("parse exception 2: " + e);
\r
764 if (!ms3.equals(ms)) {
\r
766 log("\nError: Re-parse of '" + result + "' gave time of " +
\r
773 String info = "\nPassed: " + pass + ", Warnings: " + warning + ", Errors: " + error;
\r
782 * Test the ZoneMeta API.
\r
784 public void TestZoneMeta() {
\r
785 // Test index by country API
\r
787 // Format: {country, zone1, zone2, ..., zoneN}
\r
788 String COUNTRY[][] = { {""},
\r
789 {"US", "America/Los_Angeles", "PST"} };
\r
790 StringBuffer buf = new StringBuffer();
\r
791 for (int i=0; i<COUNTRY.length; ++i) {
\r
792 String[] a = ZoneMeta.getAvailableIDs(COUNTRY[i][0]);
\r
794 buf.append("Country \"" + COUNTRY[i][0] + "\": [");
\r
795 // Use bitmask to track which of the expected zones we see
\r
797 for (int j=0; j<a.length; ++j) {
\r
798 if (j!=0) buf.append(", ");
\r
800 for (int k=1; k<COUNTRY[i].length; ++k) {
\r
801 if ((mask & (1<<k)) == 0 &&
\r
802 a[j].equals(COUNTRY[i][k])) {
\r
809 // Check bitmask to see if we saw all expected zones
\r
810 if (mask == (1 << (COUNTRY[i].length-1))-1) {
\r
811 logln(buf.toString());
\r
813 errln(buf.toString());
\r
817 // Test equivalent IDs API
\r
819 int n = ZoneMeta.countEquivalentIDs("PST");
\r
820 boolean ok = false;
\r
822 buf.append("Equivalent to PST: ");
\r
823 for (int i=0; i<n; ++i) {
\r
824 String id = ZoneMeta.getEquivalentID("PST", i);
\r
825 if (id.equals("America/Los_Angeles")) {
\r
828 if (i!=0) buf.append(", ");
\r
832 logln(buf.toString());
\r
834 errln(buf.toString());
\r
838 public void TestComparable() {
\r
839 GregorianCalendar c0 = new GregorianCalendar();
\r
840 GregorianCalendar c1 = new GregorianCalendar();
\r
841 c1.add(Calendar.DAY_OF_MONTH, 1);
\r
842 if (c0.compareTo(c1) >= 0) {
\r
843 errln("calendar " + c0 + " not < " + c1);
\r
845 c0.add(Calendar.MONTH, 1);
\r
846 if (c0.compareTo(c1) <= 0) {
\r
847 errln("calendar " + c0 + " not > " + c1);
\r
850 c0.setTimeInMillis(c1.getTimeInMillis());
\r
851 if (c0.compareTo(c1) != 0) {
\r
852 errln("calendar " + c0 + " not == " + c1);
\r
858 * Miscellaneous tests to increase coverage.
\r
860 public void TestCoverage() {
\r
861 // BuddhistCalendar
\r
862 BuddhistCalendar bcal = new BuddhistCalendar();
\r
863 /*int i =*/ bcal.getMinimum(Calendar.ERA);
\r
864 bcal.add(Calendar.YEAR, 1);
\r
865 bcal.add(Calendar.MONTH, 1);
\r
866 /*Date d = */bcal.getTime();
\r
868 // CalendarAstronomer
\r
869 // (This class should probably be made package-private.)
\r
870 CalendarAstronomer astro = new CalendarAstronomer();
\r
871 /*String s = */astro.local(0);
\r
874 ChineseCalendar ccal = new ChineseCalendar(TimeZone.getDefault(),
\r
875 Locale.getDefault());
\r
876 ccal.add(Calendar.MONTH, 1);
\r
877 ccal.add(Calendar.YEAR, 1);
\r
878 ccal.roll(Calendar.MONTH, 1);
\r
879 ccal.roll(Calendar.YEAR, 1);
\r
883 Calendar cal = Calendar.getInstance(Locale.US);
\r
884 logln(cal.toString());
\r
885 logln(cal.getDisplayName(Locale.US));
\r
886 int weekendOnset=-1;
\r
887 int weekendCease=-1;
\r
888 for (int i=Calendar.SUNDAY; i<=Calendar.SATURDAY; ++i) {
\r
889 if (cal.getDayOfWeekType(i) == Calendar.WEEKEND_ONSET) {
\r
892 if (cal.getDayOfWeekType(i) == Calendar.WEEKEND_CEASE) {
\r
896 // can't call this unless we get a transition day (unusual),
\r
897 // but make the call anyway for coverage reasons
\r
899 /*int x=*/ cal.getWeekendTransition(weekendOnset);
\r
900 /*int x=*/ cal.getWeekendTransition(weekendCease);
\r
901 } catch (IllegalArgumentException e) {}
\r
902 /*int x=*/ cal.isWeekend(new Date());
\r
904 // new GregorianCalendar(ULocale)
\r
905 GregorianCalendar gcal = new GregorianCalendar(ULocale.getDefault());
\r
907 errln("could not create GregorianCalendar with ULocale");
\r
909 logln("Calendar display name: " + gcal.getDisplayName(ULocale.getDefault()));
\r
912 //cover getAvailableULocales
\r
913 final ULocale[] locales = Calendar.getAvailableULocales();
\r
914 long count = locales.length;
\r
916 errln("getAvailableULocales return empty list");
\r
917 logln("" + count + " available ulocales in Calendar.");
\r
919 // Jitterbug 4451, for coverage
\r
920 class StubCalendar extends Calendar{
\r
922 * For serialization
\r
924 private static final long serialVersionUID = -4558903444622684759L;
\r
925 protected int handleGetLimit(int field, int limitType) {return 0;}
\r
926 protected int handleComputeMonthStart(int eyear, int month, boolean useMonth) {return 0;}
\r
927 protected int handleGetExtendedYear() {return 0;}
\r
929 if (Calendar.gregorianPreviousMonthLength(2000,2) != 29){
\r
930 errln("Year 2000 Feb should have 29 days.");
\r
932 long millis = Calendar.julianDayToMillis(Calendar.MAX_JULIAN);
\r
933 if(millis != Calendar.MAX_MILLIS){
\r
934 errln("Did not get the expected value from julianDayToMillis. Got:" + millis);
\r
936 DateFormat df = handleGetDateFormat("",Locale.getDefault());
\r
937 if (!df.equals(handleGetDateFormat("",ULocale.getDefault()))){
\r
938 errln ("Calendar.handleGetDateFormat(String, Locale) should delegate to ( ,ULocale)");
\r
940 if (!getType().equals("gregorian")){
\r
941 errln ("Calendar.getType() should be 'gregorian'");
\r
945 StubCalendar stub = new StubCalendar();
\r
949 // Tests for jb 4541
\r
950 public void TestJB4541() {
\r
951 ULocale loc = new ULocale("en_US");
\r
953 // !!! Shouldn't we have an api like this?
\r
954 // !!! Question: should this reflect those actually available in this copy of ICU, or
\r
955 // the list of types we assume is available?
\r
956 // String[] calTypes = Calendar.getAvailableTypes();
\r
957 final String[] calTypes = {
\r
958 "buddhist", "chinese", "coptic", "ethiopic", "gregorian", "hebrew",
\r
959 "islamic", "islamic-civil", "japanese", "roc"
\r
962 // constructing a DateFormat with a locale indicating a calendar type should construct a
\r
963 // date format appropriate to that calendar
\r
964 final Date time = new Date();
\r
965 for (int i = 0; i < calTypes.length; ++i) {
\r
966 ULocale aLoc = loc.setKeywordValue("calendar", calTypes[i]);
\r
967 logln("locale: " + aLoc);
\r
969 DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL,
\r
973 logln("df type: " + df.getClass().getName() + " loc: " + df.getLocale(ULocale.VALID_LOCALE));
\r
975 Calendar cal = df.getCalendar();
\r
976 // todo, what about variants of calendars, we have a type for islamic-civil, should we also have a type
\r
977 // for variants of other calendars?
\r
978 assertEquals("calendar types", cal.getType(), calTypes[i].equals("islamic-civil") ? "islamic" : calTypes[i]);
\r
979 DateFormat df2 = cal.getDateTimeFormat(DateFormat.FULL, DateFormat.FULL, ULocale.US);
\r
980 logln("df2 type: " + df2.getClass().getName() + " loc: " + df2.getLocale(ULocale.VALID_LOCALE));
\r
981 assertEquals("format results", df.format(time), df2.format(time));
\r
984 // dateFormat.setCalendar should throw exception if wrong format for calendar
\r
986 DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL,
\r
988 new ULocale("en_US@calendar=chinese"));
\r
990 logln("dateformat type: " + df.getClass().getName());
\r
992 Calendar cal = Calendar.getInstance(new ULocale("en_US@calendar=chinese"));
\r
994 logln("calendar type: " + cal.getClass().getName());
\r
998 public void TestTypes() {
\r
1000 "en_US_VALLEYGIRL",
\r
1001 "en_US_VALLEYGIRL@collation=phonebook;calendar=japanese",
\r
1002 "en_US_VALLEYGIRL@collation=phonebook;calendar=gregorian",
\r
1003 "ja_JP@calendar=japanese",
\r
1004 "th_TH@calendar=buddhist",
\r
1005 "ja_JP_TRADITIONAL",
\r
1006 "th_TH_TRADITIONAL",
\r
1007 "th_TH_TRADITIONAL@calendar=gregorian",
\r
1009 "th_TH", // Default calendar for th_TH is buddhist
\r
1010 "th", // th's default region is TH and buddhist is used as default for TH
\r
1011 // FIXME: ICU Service canonicalize en_TH to en, so TH is ignored in Calendar instantiation. See #6816.
\r
1012 // "en_TH", // Default calendar for any locales with region TH is buddhist
\r
1015 String[] types = {
\r
1027 // FIXME: ICU Service canonicalize en_TH to en, so TH is ignored in Calendar instantiation. See #6816.
\r
1031 for (int i = 0; i < locs.length; i++) {
\r
1032 Calendar cal = Calendar.getInstance(new ULocale(locs[i]));
\r
1033 if (!cal.getType().equals(types[i])) {
\r
1034 errln(locs[i] + " Calendar type " + cal.getType() + " instead of " + types[i]);
\r