001: /*
002: *******************************************************************************
003: * Copyright (C) 2000-2006, International Business Machines Corporation and
004: * others. All Rights Reserved.
005: *******************************************************************************
006: */
007: package com.ibm.icu.dev.test.calendar;
008:
009: import java.util.Date;
010: import java.util.Locale;
011: import java.text.ParseException;
012:
013: import com.ibm.icu.impl.LocaleUtility;
014: import com.ibm.icu.impl.ZoneMeta;
015: import com.ibm.icu.impl.CalendarAstronomer;
016: import com.ibm.icu.text.DateFormat;
017: import com.ibm.icu.text.SimpleDateFormat;
018: import com.ibm.icu.util.*;
019:
020: /**
021: * @test
022: * @summary Tests of new functionality in IBMCalendar
023: */
024: public class IBMCalendarTest extends CalendarTest {
025:
026: public static void main(String[] args) throws Exception {
027: new IBMCalendarTest().run(args);
028: }
029:
030: /**
031: * Test weekend support in IBMCalendar.
032: *
033: * NOTE: This test will have to be updated when the isWeekend() etc.
034: * API is finalized later.
035: *
036: * In particular, the test will have to be rewritten to instantiate
037: * a Calendar in the given locale (using getInstance()) and call
038: * that Calendar's isWeekend() etc. methods.
039: */
040: public void TestWeekend() {
041: SimpleDateFormat fmt = new SimpleDateFormat(
042: "EEE MMM dd yyyy G HH:mm:ss.SSS");
043:
044: // NOTE
045: // This test tests for specific locale data. This is probably okay
046: // as far as US data is concerned, but if the Arabic/Bahrain data
047: // changes, this test will have to be updated.
048:
049: // Test specific days
050: Object[] DATA1 = { Locale.US, new int[] { // Saturday:Sunday
051: 2000, Calendar.MARCH, 17, 23, 0, 0, // Fri 23:00
052: 2000, Calendar.MARCH, 18, 0, -1, 0, // Fri 23:59:59.999
053: 2000, Calendar.MARCH, 18, 0, 0, 1, // Sat 00:00
054: 2000, Calendar.MARCH, 18, 15, 0, 1, // Sat 15:00
055: 2000, Calendar.MARCH, 19, 23, 0, 1, // Sun 23:00
056: 2000, Calendar.MARCH, 20, 0, -1, 1, // Sun 23:59:59.999
057: 2000, Calendar.MARCH, 20, 0, 0, 0, // Mon 00:00
058: 2000, Calendar.MARCH, 20, 8, 0, 0, // Mon 08:00
059: }, new Locale("ar", "BH"), new int[] { // Thursday:Friday
060: 2000, Calendar.MARCH, 15, 23, 0, 0, // Wed 23:00
061: 2000, Calendar.MARCH, 16, 0, -1, 0, // Wed 23:59:59.999
062: 2000, Calendar.MARCH, 16, 0, 0, 1, // Thu 00:00
063: 2000, Calendar.MARCH, 16, 15, 0, 1, // Thu 15:00
064: 2000, Calendar.MARCH, 17, 23, 0, 1, // Fri 23:00
065: 2000, Calendar.MARCH, 18, 0, -1, 1, // Fri 23:59:59.999
066: 2000, Calendar.MARCH, 18, 0, 0, 0, // Sat 00:00
067: 2000, Calendar.MARCH, 18, 8, 0, 0, // Sat 08:00
068: }, };
069:
070: // Test days of the week
071: Object[] DATA2 = {
072: Locale.US,
073: new int[] { Calendar.MONDAY, Calendar.WEEKDAY,
074: Calendar.FRIDAY, Calendar.WEEKDAY,
075: Calendar.SATURDAY, Calendar.WEEKEND,
076: Calendar.SUNDAY, Calendar.WEEKEND_CEASE, },
077: new Locale("ar", "BH"), new int[] { // Thursday:Friday
078: Calendar.WEDNESDAY, Calendar.WEEKDAY,
079: Calendar.SATURDAY, Calendar.WEEKDAY,
080: Calendar.THURSDAY, Calendar.WEEKEND,
081: Calendar.FRIDAY, Calendar.WEEKEND_CEASE, }, };
082:
083: // We only test the getDayOfWeekType() and isWeekend() APIs.
084: // The getWeekendTransition() API is tested indirectly via the
085: // isWeekend() API, which calls it.
086:
087: for (int i1 = 0; i1 < DATA1.length; i1 += 2) {
088: Locale loc = (Locale) DATA1[i1];
089: int[] data = (int[]) DATA1[i1 + 1];
090: Calendar cal = Calendar.getInstance(loc);
091: logln("Locale: " + loc);
092: for (int i = 0; i < data.length; i += 6) {
093: cal.clear();
094: cal.set(data[i], data[i + 1], data[i + 2], data[i + 3],
095: 0, 0);
096: if (data[i + 4] != 0) {
097: cal.setTime(new Date(cal.getTime().getTime()
098: + data[i + 4]));
099: }
100: boolean isWeekend = cal.isWeekend();
101: boolean ok = isWeekend == (data[i + 5] != 0);
102: if (ok) {
103: logln("Ok: " + fmt.format(cal.getTime())
104: + " isWeekend=" + isWeekend);
105: } else {
106: errln("FAIL: " + fmt.format(cal.getTime())
107: + " isWeekend=" + isWeekend + ", expected="
108: + (!isWeekend));
109: }
110: }
111: }
112:
113: for (int i2 = 0; i2 < DATA2.length; i2 += 2) {
114: Locale loc = (Locale) DATA2[i2];
115: int[] data = (int[]) DATA2[i2 + 1];
116: logln("Locale: " + loc);
117: Calendar cal = Calendar.getInstance(loc);
118: for (int i = 0; i < data.length; i += 2) {
119: int type = cal.getDayOfWeekType(data[i]);
120: int exp = data[i + 1];
121: if (type == exp) {
122: logln("Ok: DOW " + data[i] + " type=" + type);
123: } else {
124: errln("FAIL: DOW " + data[i] + " type=" + type
125: + ", expected=" + exp);
126: }
127: }
128: }
129: }
130:
131: /**
132: * Run a test of a quasi-Gregorian calendar. This is a calendar
133: * that behaves like a Gregorian but has different year/era mappings.
134: * The int[] data array should have the format:
135: *
136: * { era, year, gregorianYear, month, dayOfMonth, ... }
137: */
138: void quasiGregorianTest(Calendar cal, int[] data) {
139: // As of JDK 1.4.1_01, using the Sun JDK GregorianCalendar as
140: // a reference throws us off by one hour. This is most likely
141: // due to the JDK 1.4 incorporation of historical time zones.
142: //java.util.Calendar grego = java.util.Calendar.getInstance();
143: Calendar grego = Calendar.getInstance();
144: for (int i = 0; i < data.length;) {
145: int era = data[i++];
146: int year = data[i++];
147: int gregorianYear = data[i++];
148: int month = data[i++];
149: int dayOfMonth = data[i++];
150:
151: grego.clear();
152: grego.set(gregorianYear, month, dayOfMonth);
153: Date D = grego.getTime();
154:
155: cal.clear();
156: cal.set(Calendar.ERA, era);
157: cal.set(year, month, dayOfMonth);
158: Date d = cal.getTime();
159: if (d.equals(D)) {
160: logln("OK: " + era + ":" + year + "/" + (month + 1)
161: + "/" + dayOfMonth + " => " + d);
162: } else {
163: errln("Fail: " + era + ":" + year + "/" + (month + 1)
164: + "/" + dayOfMonth + " => " + d + ", expected "
165: + D);
166: }
167:
168: cal.clear();
169: cal.setTime(D);
170: int e = cal.get(Calendar.ERA);
171: int y = cal.get(Calendar.YEAR);
172: if (y == year && e == era) {
173: logln("OK: " + D + " => " + cal.get(Calendar.ERA) + ":"
174: + cal.get(Calendar.YEAR) + "/"
175: + (cal.get(Calendar.MONTH) + 1) + "/"
176: + cal.get(Calendar.DATE));
177: } else {
178: logln("Fail: " + D + " => " + cal.get(Calendar.ERA)
179: + ":" + cal.get(Calendar.YEAR) + "/"
180: + (cal.get(Calendar.MONTH) + 1) + "/"
181: + cal.get(Calendar.DATE) + ", expected " + era
182: + ":" + year + "/" + (month + 1) + "/"
183: + dayOfMonth);
184: }
185: }
186: }
187:
188: /**
189: * Verify that BuddhistCalendar shifts years to Buddhist Era but otherwise
190: * behaves like GregorianCalendar.
191: */
192: public void TestBuddhist() {
193: quasiGregorianTest(new BuddhistCalendar(), new int[] {
194: // BE 2542 == 1999 CE
195: 0, 2542, 1999, Calendar.JUNE, 4 });
196: }
197:
198: public void TestBuddhistCoverage() {
199: {
200: // new BuddhistCalendar(ULocale)
201: BuddhistCalendar cal = new BuddhistCalendar(ULocale
202: .getDefault());
203: if (cal == null) {
204: errln("could not create BuddhistCalendar with ULocale");
205: }
206: }
207:
208: {
209: // new BuddhistCalendar(TimeZone,ULocale)
210: BuddhistCalendar cal = new BuddhistCalendar(TimeZone
211: .getDefault(), ULocale.getDefault());
212: if (cal == null) {
213: errln("could not create BuddhistCalendar with TimeZone ULocale");
214: }
215: }
216:
217: {
218: // new BuddhistCalendar(TimeZone)
219: BuddhistCalendar cal = new BuddhistCalendar(TimeZone
220: .getDefault());
221: if (cal == null) {
222: errln("could not create BuddhistCalendar with TimeZone");
223: }
224: }
225:
226: {
227: // new BuddhistCalendar(Locale)
228: BuddhistCalendar cal = new BuddhistCalendar(Locale
229: .getDefault());
230: if (cal == null) {
231: errln("could not create BuddhistCalendar with Locale");
232: }
233: }
234:
235: {
236: // new BuddhistCalendar(TimeZone, Locale)
237: BuddhistCalendar cal = new BuddhistCalendar(TimeZone
238: .getDefault(), Locale.getDefault());
239: if (cal == null) {
240: errln("could not create BuddhistCalendar with TimeZone and Locale");
241: }
242: }
243:
244: {
245: // new BuddhistCalendar(Date)
246: BuddhistCalendar cal = new BuddhistCalendar(new Date());
247: if (cal == null) {
248: errln("could not create BuddhistCalendar with Date");
249: }
250: }
251:
252: {
253: // new BuddhistCalendar(int year, int month, int date)
254: BuddhistCalendar cal = new BuddhistCalendar(2543,
255: Calendar.MAY, 22);
256: if (cal == null) {
257: errln("could not create BuddhistCalendar with year,month,data");
258: }
259: }
260:
261: {
262: // new BuddhistCalendar(int year, int month, int date, int hour, int minute, int second)
263: BuddhistCalendar cal = new BuddhistCalendar(2543,
264: Calendar.MAY, 22, 1, 1, 1);
265: if (cal == null) {
266: errln("could not create BuddhistCalendar with year,month,date,hour,minute,second");
267: }
268: }
269:
270: {
271: // data
272: BuddhistCalendar cal = new BuddhistCalendar(2543,
273: Calendar.MAY, 22);
274: Date time = cal.getTime();
275:
276: String[] calendarLocales = { "th_TH" };
277:
278: String[] formatLocales = { "en", "ar", "hu", "th" };
279:
280: for (int i = 0; i < calendarLocales.length; ++i) {
281: String calLocName = calendarLocales[i];
282: Locale calLocale = LocaleUtility
283: .getLocaleFromName(calLocName);
284: cal = new BuddhistCalendar(calLocale);
285:
286: for (int j = 0; j < formatLocales.length; ++j) {
287: String locName = formatLocales[j];
288: Locale formatLocale = LocaleUtility
289: .getLocaleFromName(locName);
290: DateFormat format = DateFormat.getDateTimeInstance(
291: cal, DateFormat.FULL, DateFormat.FULL,
292: formatLocale);
293: logln(calLocName + "/" + locName + " --> "
294: + format.format(time));
295: }
296: }
297: }
298: }
299:
300: /**
301: * Verify that JapaneseCalendar shifts years to Buddhist Era but otherwise
302: * behaves like GregorianCalendar.
303: */
304: public void TestJapanese() {
305: // First make sure this test works for GregorianCalendar
306: int[] control = { GregorianCalendar.AD, 1868, 1868,
307: Calendar.SEPTEMBER, 8, GregorianCalendar.AD, 1868,
308: 1868, Calendar.SEPTEMBER, 9, GregorianCalendar.AD,
309: 1869, 1869, Calendar.JUNE, 4, GregorianCalendar.AD,
310: 1912, 1912, Calendar.JULY, 29, GregorianCalendar.AD,
311: 1912, 1912, Calendar.JULY, 30, GregorianCalendar.AD,
312: 1912, 1912, Calendar.AUGUST, 1, };
313: quasiGregorianTest(new GregorianCalendar(), control);
314:
315: int[] data = { JapaneseCalendar.MEIJI, 1, 1868,
316: Calendar.SEPTEMBER, 8, JapaneseCalendar.MEIJI, 1, 1868,
317: Calendar.SEPTEMBER, 9, JapaneseCalendar.MEIJI, 2, 1869,
318: Calendar.JUNE, 4, JapaneseCalendar.MEIJI, 45, 1912,
319: Calendar.JULY, 29, JapaneseCalendar.TAISHO, 1, 1912,
320: Calendar.JULY, 30, JapaneseCalendar.TAISHO, 1, 1912,
321: Calendar.AUGUST, 1, };
322: quasiGregorianTest(new JapaneseCalendar(), data);
323: }
324:
325: /**
326: * Test limits of the Gregorian calendar.
327: */
328: public void TestGregorianLimits() {
329: // Final parameter is either number of days, if > 0, or test
330: // duration in seconds, if < 0.
331: Calendar cal = Calendar.getInstance();
332: cal.set(2004, Calendar.JANUARY, 1);
333: doLimitsTest(new GregorianCalendar(), null, cal.getTime(), -10);
334: }
335:
336: /**
337: * Test behavior of fieldDifference around leap years. Also test a large
338: * field difference to check binary search.
339: */
340: public void TestLeapFieldDifference() {
341: Calendar cal = Calendar.getInstance();
342: cal.set(2004, Calendar.FEBRUARY, 29);
343: Date date2004 = cal.getTime();
344: cal.set(2000, Calendar.FEBRUARY, 29);
345: Date date2000 = cal.getTime();
346: int y = cal.fieldDifference(date2004, Calendar.YEAR);
347: int d = cal.fieldDifference(date2004, Calendar.DAY_OF_YEAR);
348: if (d == 0) {
349: logln("Ok: 2004/Feb/29 - 2000/Feb/29 = " + y + " years, "
350: + d + " days");
351: } else {
352: errln("FAIL: 2004/Feb/29 - 2000/Feb/29 = " + y + " years, "
353: + d + " days");
354: }
355: cal.setTime(date2004);
356: y = cal.fieldDifference(date2000, Calendar.YEAR);
357: d = cal.fieldDifference(date2000, Calendar.DAY_OF_YEAR);
358: if (d == 0) {
359: logln("Ok: 2000/Feb/29 - 2004/Feb/29 = " + y + " years, "
360: + d + " days");
361: } else {
362: errln("FAIL: 2000/Feb/29 - 2004/Feb/29 = " + y + " years, "
363: + d + " days");
364: }
365: // Test large difference
366: cal.set(2001, Calendar.APRIL, 5); // 2452005
367: Date ayl = cal.getTime();
368: cal.set(1964, Calendar.SEPTEMBER, 7); // 2438646
369: Date asl = cal.getTime();
370: d = cal.fieldDifference(ayl, Calendar.DAY_OF_MONTH);
371: cal.setTime(ayl);
372: int d2 = cal.fieldDifference(asl, Calendar.DAY_OF_MONTH);
373: if (d == -d2 && d == 13359) {
374: logln("Ok: large field difference symmetrical " + d);
375: } else {
376: logln("FAIL: large field difference incorrect " + d + ", "
377: + d2 + ", expect +/- 13359");
378: }
379: }
380:
381: /**
382: * Test ms_MY "Malay (Malaysia)" locale. Bug 1543.
383: */
384: public void TestMalaysianInstance() {
385: Locale loc = new Locale("ms", "MY"); // Malay (Malaysia)
386: Calendar cal = Calendar.getInstance(loc);
387: if (cal == null) {
388: errln("could not create Malaysian instance");
389: }
390: }
391:
392: /**
393: * setFirstDayOfWeek and setMinimalDaysInFirstWeek may change the
394: * field <=> time mapping, since they affect the interpretation of
395: * the WEEK_OF_MONTH or WEEK_OF_YEAR fields.
396: */
397: public void TestWeekShift() {
398: Calendar cal = new GregorianCalendar(TimeZone
399: .getTimeZone("America/Los_Angeles"), new Locale("en",
400: "US"));
401: cal.setTime(new Date(997257600000L)); // Wed Aug 08 01:00:00 PDT 2001
402: // In pass one, change the first day of week so that the weeks
403: // shift in August 2001. In pass two, change the minimal days
404: // in the first week so that the weeks shift in August 2001.
405: // August 2001
406: // Su Mo Tu We Th Fr Sa
407: // 1 2 3 4
408: // 5 6 7 8 9 10 11
409: // 12 13 14 15 16 17 18
410: // 19 20 21 22 23 24 25
411: // 26 27 28 29 30 31
412: for (int pass = 0; pass < 2; ++pass) {
413: if (pass == 0) {
414: cal.setFirstDayOfWeek(Calendar.WEDNESDAY);
415: cal.setMinimalDaysInFirstWeek(4);
416: } else {
417: cal.setFirstDayOfWeek(Calendar.SUNDAY);
418: cal.setMinimalDaysInFirstWeek(4);
419: }
420: cal.add(Calendar.DATE, 1); // Force recalc
421: cal.add(Calendar.DATE, -1);
422:
423: Date time1 = cal.getTime(); // Get time -- should not change
424:
425: // Now change a week parameter and then force a recalc.
426: // The bug is that the recalc should not be necessary --
427: // calendar should do so automatically.
428: if (pass == 0) {
429: cal.setFirstDayOfWeek(Calendar.THURSDAY);
430: } else {
431: cal.setMinimalDaysInFirstWeek(5);
432: }
433:
434: int woy1 = cal.get(Calendar.WEEK_OF_YEAR);
435: int wom1 = cal.get(Calendar.WEEK_OF_MONTH);
436:
437: cal.add(Calendar.DATE, 1); // Force recalc
438: cal.add(Calendar.DATE, -1);
439:
440: int woy2 = cal.get(Calendar.WEEK_OF_YEAR);
441: int wom2 = cal.get(Calendar.WEEK_OF_MONTH);
442:
443: Date time2 = cal.getTime();
444:
445: if (!time1.equals(time2)) {
446: errln("FAIL: shifting week should not alter time");
447: } else {
448: logln(time1.toString());
449: }
450: if (woy1 == woy2 && wom1 == wom2) {
451: logln("Ok: WEEK_OF_YEAR: " + woy1 + ", WEEK_OF_MONTH: "
452: + wom1);
453: } else {
454: errln("FAIL: WEEK_OF_YEAR: " + woy1 + " => " + woy2
455: + ", WEEK_OF_MONTH: " + wom1 + " => " + wom2
456: + " after week shift");
457: }
458: }
459: }
460:
461: /**
462: * Make sure that when adding a day, we actually wind up in a
463: * different day. The DST adjustments we use to keep the hour
464: * constant across DST changes can backfire and change the day.
465: */
466: public void TestTimeZoneTransitionAdd() {
467: Locale locale = Locale.US; // could also be CHINA
468: SimpleDateFormat dateFormat = new SimpleDateFormat(
469: "MM/dd/yyyy HH:mm z", locale);
470:
471: String tz[] = TimeZone.getAvailableIDs();
472:
473: for (int z = 0; z < tz.length; ++z) {
474: TimeZone t = TimeZone.getTimeZone(tz[z]);
475: dateFormat.setTimeZone(t);
476:
477: Calendar cal = Calendar.getInstance(t, locale);
478: cal.clear();
479: // Scan the year 2003, overlapping the edges of the year
480: cal.set(Calendar.YEAR, 2002);
481: cal.set(Calendar.MONTH, Calendar.DECEMBER);
482: cal.set(Calendar.DAY_OF_MONTH, 25);
483:
484: for (int i = 0; i < 365 + 10; ++i) {
485: Date yesterday = cal.getTime();
486: int yesterday_day = cal.get(Calendar.DAY_OF_MONTH);
487: cal.add(Calendar.DAY_OF_MONTH, 1);
488: if (yesterday_day == cal.get(Calendar.DAY_OF_MONTH)) {
489: errln(tz[z] + " " + dateFormat.format(yesterday)
490: + " +1d= "
491: + dateFormat.format(cal.getTime()));
492: }
493: }
494: }
495: }
496:
497: public void TestJB1684() {
498: class TestData {
499: int year;
500: int month;
501: int date;
502: int womyear;
503: int wommon;
504: int wom;
505: int dow;
506: String data;
507: String normalized;
508:
509: public TestData(int year, int month, int date, int womyear,
510: int wommon, int wom, int dow, String data,
511: String normalized) {
512: this .year = year;
513: this .month = month - 1;
514: this .date = date;
515: this .womyear = womyear;
516: this .wommon = wommon - 1;
517: this .wom = wom;
518: this .dow = dow;
519: this .data = data; // year, month, week of month, day
520: this .normalized = data;
521: if (normalized != null)
522: this .normalized = normalized;
523: }
524: }
525:
526: // July 2001 August 2001 January 2002
527: // Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
528: // 1 2 3 4 5 6 7 1 2 3 4 1 2 3 4 5
529: // 8 9 10 11 12 13 14 5 6 7 8 9 10 11 6 7 8 9 10 11 12
530: // 15 16 17 18 19 20 21 12 13 14 15 16 17 18 13 14 15 16 17 18 19
531: // 22 23 24 25 26 27 28 19 20 21 22 23 24 25 20 21 22 23 24 25 26
532: // 29 30 31 26 27 28 29 30 31 27 28 29 30 31
533: TestData[] tests = {
534: new TestData(2001, 8, 6, 2001, 8, 2, Calendar.MONDAY,
535: "2001 08 02 Mon", null),
536: new TestData(2001, 8, 7, 2001, 8, 2, Calendar.TUESDAY,
537: "2001 08 02 Tue", null),
538: new TestData(2001, 8, 5,/*12,*/2001, 8, 2,
539: Calendar.SUNDAY, "2001 08 02 Sun", null),
540: new TestData(2001, 8, 6, /*7, 30,*/2001, 7, 6,
541: Calendar.MONDAY, "2001 07 06 Mon",
542: "2001 08 02 Mon"),
543: new TestData(2001, 8, 7, /*7, 31,*/2001, 7, 6,
544: Calendar.TUESDAY, "2001 07 06 Tue",
545: "2001 08 02 Tue"),
546: new TestData(2001, 8, 5, 2001, 7, 6, Calendar.SUNDAY,
547: "2001 07 06 Sun", "2001 08 02 Sun"),
548: new TestData(2001, 7, 30, 2001, 8, 1, Calendar.MONDAY,
549: "2001 08 01 Mon", "2001 07 05 Mon"),
550: new TestData(2001, 7, 31, 2001, 8, 1, Calendar.TUESDAY,
551: "2001 08 01 Tue", "2001 07 05 Tue"),
552: new TestData(2001, 7, 29, /*8, 5,*/2001, 8, 1,
553: Calendar.SUNDAY, "2001 08 01 Sun",
554: "2001 07 05 Sun"),
555: new TestData(2001, 12, 31, 2001, 12, 6,
556: Calendar.MONDAY, "2001 12 06 Mon", null),
557: new TestData(2002, 1, 1, 2002, 1, 1, Calendar.TUESDAY,
558: "2002 01 01 Tue", null),
559: new TestData(2002, 1, 2, 2002, 1, 1,
560: Calendar.WEDNESDAY, "2002 01 01 Wed", null),
561: new TestData(2002, 1, 3, 2002, 1, 1, Calendar.THURSDAY,
562: "2002 01 01 Thu", null),
563: new TestData(2002, 1, 4, 2002, 1, 1, Calendar.FRIDAY,
564: "2002 01 01 Fri", null),
565: new TestData(2002, 1, 5, 2002, 1, 1, Calendar.SATURDAY,
566: "2002 01 01 Sat", null),
567: new TestData(2001, 12, 30, /*2002, 1, 6,*/2002, 1, 1,
568: Calendar.SUNDAY, "2002 01 01 Sun",
569: "2001 12 06 Sun"), };
570:
571: int pass = 0, error = 0, warning = 0;
572:
573: final String pattern = "yyyy MM WW EEE";
574: GregorianCalendar cal = new GregorianCalendar();
575: SimpleDateFormat sdf = new SimpleDateFormat(pattern);
576: sdf.setCalendar(cal);
577:
578: cal.setFirstDayOfWeek(Calendar.SUNDAY);
579: cal.setMinimalDaysInFirstWeek(1);
580:
581: for (int i = 0; i < tests.length; ++i) {
582: TestData test = tests[i];
583: log("\n-----\nTesting round trip of " + test.year + " "
584: + (test.month + 1) + " " + test.date
585: + " (written as) " + test.data);
586:
587: cal.clear();
588: cal.set(test.year, test.month, test.date);
589: Date ms = cal.getTime();
590:
591: cal.clear();
592: cal.set(Calendar.YEAR, test.womyear);
593: cal.set(Calendar.MONTH, test.wommon);
594: cal.set(Calendar.WEEK_OF_MONTH, test.wom);
595: cal.set(Calendar.DAY_OF_WEEK, test.dow);
596: Date ms2 = cal.getTime();
597:
598: if (!ms2.equals(ms)) {
599: log("\nError: GregorianCalendar.DOM gave " + ms
600: + "\n GregorianCalendar.WOM gave " + ms2);
601: error++;
602: } else {
603: pass++;
604: }
605:
606: ms2 = null;
607: try {
608: ms2 = sdf.parse(test.data);
609: } catch (ParseException e) {
610: errln("parse exception: " + e);
611: }
612:
613: if (!ms2.equals(ms)) {
614: log("\nError: GregorianCalendar gave " + ms
615: + "\n SimpleDateFormat.parse gave " + ms2);
616: error++;
617: } else {
618: pass++;
619: }
620:
621: String result = sdf.format(ms);
622: if (!result.equals(test.normalized)) {
623: log("\nWarning: format of '" + test.data + "' gave"
624: + "\n '" + result + "'"
625: + "\n expected '" + test.normalized
626: + "'");
627: warning++;
628: } else {
629: pass++;
630: }
631:
632: Date ms3 = null;
633: try {
634: ms3 = sdf.parse(result);
635: } catch (ParseException e) {
636: errln("parse exception 2: " + e);
637: }
638:
639: if (!ms3.equals(ms)) {
640: error++;
641: log("\nError: Re-parse of '" + result
642: + "' gave time of " + "\n " + ms3
643: + "\n not " + ms);
644: } else {
645: pass++;
646: }
647: }
648: String info = "\nPassed: " + pass + ", Warnings: " + warning
649: + ", Errors: " + error;
650: if (error > 0) {
651: errln(info);
652: } else {
653: logln(info);
654: }
655: }
656:
657: /**
658: * Test the ZoneMeta API.
659: */
660: public void TestZoneMeta() {
661: // Test index by country API
662:
663: // Format: {country, zone1, zone2, ..., zoneN}
664: String COUNTRY[][] = { { "" },
665: { "US", "America/Los_Angeles", "PST" } };
666: StringBuffer buf = new StringBuffer();
667: for (int i = 0; i < COUNTRY.length; ++i) {
668: String[] a = ZoneMeta.getAvailableIDs(COUNTRY[i][0]);
669: buf.setLength(0);
670: buf.append("Country \"" + COUNTRY[i][0] + "\": [");
671: // Use bitmask to track which of the expected zones we see
672: int mask = 0;
673: for (int j = 0; j < a.length; ++j) {
674: if (j != 0)
675: buf.append(", ");
676: buf.append(a[j]);
677: for (int k = 1; k < COUNTRY[i].length; ++k) {
678: if ((mask & (1 << k)) == 0
679: && a[j].equals(COUNTRY[i][k])) {
680: mask |= (1 << k);
681: }
682: }
683: }
684: buf.append("]");
685: mask >>= 1;
686: // Check bitmask to see if we saw all expected zones
687: if (mask == (1 << (COUNTRY[i].length - 1)) - 1) {
688: logln(buf.toString());
689: } else {
690: errln(buf.toString());
691: }
692: }
693:
694: // Test equivalent IDs API
695:
696: int n = ZoneMeta.countEquivalentIDs("PST");
697: boolean ok = false;
698: buf.setLength(0);
699: buf.append("Equivalent to PST: ");
700: for (int i = 0; i < n; ++i) {
701: String id = ZoneMeta.getEquivalentID("PST", i);
702: if (id.equals("America/Los_Angeles")) {
703: ok = true;
704: }
705: if (i != 0)
706: buf.append(", ");
707: buf.append(id);
708: }
709: if (ok) {
710: logln(buf.toString());
711: } else {
712: errln(buf.toString());
713: }
714: }
715:
716: public void TestComparable() {
717: GregorianCalendar c0 = new GregorianCalendar();
718: GregorianCalendar c1 = new GregorianCalendar();
719: c1.add(Calendar.DAY_OF_MONTH, 1);
720: if (c0.compareTo(c1) >= 0) {
721: errln("calendar " + c0 + " not < " + c1);
722: }
723: c0.add(Calendar.MONTH, 1);
724: if (c0.compareTo(c1) <= 0) {
725: errln("calendar " + c0 + " not > " + c1);
726: }
727:
728: c0.setTimeInMillis(c1.getTimeInMillis());
729: if (c0.compareTo(c1) != 0) {
730: errln("calendar " + c0 + " not == " + c1);
731: }
732:
733: // coverage
734: try {
735: c0.compareTo((Object) null);
736: errln("calendar.compareTo didn't object to null arg");
737: } catch (NullPointerException npe) {
738: logln("PASS: calendar.compareTo objected to null arg");
739: }
740: }
741:
742: /**
743: * Miscellaneous tests to increase coverage.
744: */
745: public void TestCoverage() {
746: // BuddhistCalendar
747: BuddhistCalendar bcal = new BuddhistCalendar();
748: /*int i =*/bcal.getMinimum(Calendar.ERA);
749: bcal.add(Calendar.YEAR, 1);
750: bcal.add(Calendar.MONTH, 1);
751: /*Date d = */bcal.getTime();
752:
753: // CalendarAstronomer
754: // (This class should probably be made package-private.)
755: CalendarAstronomer astro = new CalendarAstronomer();
756: /*String s = */astro.local(0);
757:
758: // ChineseCalendar
759: ChineseCalendar ccal = new ChineseCalendar(TimeZone
760: .getDefault(), Locale.getDefault());
761: ccal.add(Calendar.MONTH, 1);
762: ccal.add(Calendar.YEAR, 1);
763: ccal.roll(Calendar.MONTH, 1);
764: ccal.roll(Calendar.YEAR, 1);
765: ccal.getTime();
766:
767: // ICU 2.6
768: Calendar cal = Calendar.getInstance(Locale.US);
769: logln(cal.toString());
770: logln(cal.getDisplayName(Locale.US));
771: int weekendOnset = -1;
772: int weekendCease = -1;
773: for (int i = Calendar.SUNDAY; i <= Calendar.SATURDAY; ++i) {
774: if (cal.getDayOfWeekType(i) == Calendar.WEEKEND_ONSET) {
775: weekendOnset = i;
776: }
777: if (cal.getDayOfWeekType(i) == Calendar.WEEKEND_CEASE) {
778: weekendCease = i;
779: }
780: }
781: // can't call this unless we get a transition day (unusual),
782: // but make the call anyway for coverage reasons
783: try {
784: /*int x=*/cal.getWeekendTransition(weekendOnset);
785: /*int x=*/cal.getWeekendTransition(weekendCease);
786: } catch (IllegalArgumentException e) {
787: }
788: /*int x=*/cal.isWeekend(new Date());
789:
790: // new GregorianCalendar(ULocale)
791: GregorianCalendar gcal = new GregorianCalendar(ULocale
792: .getDefault());
793: if (gcal == null) {
794: errln("could not create GregorianCalendar with ULocale");
795: } else {
796: logln("Calendar display name: "
797: + gcal.getDisplayName(ULocale.getDefault()));
798: }
799:
800: //cover getAvailableULocales
801: final ULocale[] locales = Calendar.getAvailableULocales();
802: long count = locales.length;
803: if (count == 0)
804: errln("getAvailableULocales return empty list");
805: logln("" + count + " available ulocales in Calendar.");
806:
807: // Jitterbug 4451, for coverage
808: class StubCalendar extends Calendar {
809: protected int handleGetLimit(int field, int limitType) {
810: return 0;
811: }
812:
813: protected int handleComputeMonthStart(int eyear, int month,
814: boolean useMonth) {
815: return 0;
816: }
817:
818: protected int handleGetExtendedYear() {
819: return 0;
820: }
821:
822: public void run() {
823: if (Calendar.gregorianPreviousMonthLength(2000, 2) != 29) {
824: errln("Year 2000 Feb should have 29 days.");
825: }
826: long millis = Calendar
827: .julianDayToMillis(Calendar.MAX_JULIAN);
828: if (millis != Calendar.MAX_MILLIS) {
829: errln("Did not get the expected value from julianDayToMillis. Got:"
830: + millis);
831: }
832: DateFormat df = handleGetDateFormat("", Locale
833: .getDefault());
834: if (!df.equals(handleGetDateFormat("", ULocale
835: .getDefault()))) {
836: errln("Calendar.handleGetDateFormat(String, Locale) should delegate to ( ,ULocale)");
837: }
838: if (!getType().equals("gregorian")) {
839: errln("Calendar.getType() should be 'gregorian'");
840: }
841: }
842: }
843: StubCalendar stub = new StubCalendar();
844: stub.run();
845: }
846:
847: // Tests for jb 4541
848: public void TestJB4541() {
849: ULocale loc = new ULocale("en_US");
850:
851: // !!! Shouldn't we have an api like this?
852: // !!! Question: should this reflect those actually available in this copy of ICU, or
853: // the list of types we assume is available?
854: // String[] calTypes = Calendar.getAvailableTypes();
855: final String[] calTypes = { "buddhist", "chinese", "coptic",
856: "ethiopic", "gregorian", "hebrew", "islamic",
857: "islamic-civil", "japanese", };
858:
859: // constructing a DateFormat with a locale indicating a calendar type should construct a
860: // date format appropriate to that calendar
861: final Date time = new Date();
862: for (int i = 0; i < calTypes.length; ++i) {
863: ULocale aLoc = loc.setKeywordValue("calendar", calTypes[i]);
864: logln("locale: " + aLoc);
865:
866: DateFormat df = DateFormat.getDateTimeInstance(
867: DateFormat.FULL, DateFormat.FULL, aLoc);
868:
869: logln("df type: " + df.getClass().getName() + " loc: "
870: + df.getLocale(ULocale.VALID_LOCALE));
871:
872: Calendar cal = df.getCalendar();
873: // todo, what about variants of calendars, we have a type for islamic-civil, should we also have a type
874: // for variants of other calendars?
875: assertEquals("calendar types", cal.getType(), calTypes[i]
876: .equals("islamic-civil") ? "islamic" : calTypes[i]);
877: DateFormat df2 = cal.getDateTimeFormat(DateFormat.FULL,
878: DateFormat.FULL, ULocale.US);
879: logln("df2 type: " + df2.getClass().getName() + " loc: "
880: + df2.getLocale(ULocale.VALID_LOCALE));
881: assertEquals("format results", df.format(time), df2
882: .format(time));
883: }
884:
885: // dateFormat.setCalendar should throw exception if wrong format for calendar
886: if (false) {
887: DateFormat df = DateFormat.getDateTimeInstance(
888: DateFormat.FULL, DateFormat.FULL, new ULocale(
889: "en_US@calendar=chinese"));
890:
891: logln("dateformat type: " + df.getClass().getName());
892:
893: Calendar cal = Calendar.getInstance(new ULocale(
894: "en_US@calendar=chinese"));
895:
896: logln("calendar type: " + cal.getClass().getName());
897: }
898: }
899: }
|