1 /*********************************************************************
2 * Copyright (C) 2000-2013, International Business Machines Corporation and
3 * others. All Rights Reserved.
4 *********************************************************************
6 package com.ibm.icu.dev.test.calendar;
8 import java.util.Locale;
10 import com.ibm.icu.text.ChineseDateFormat;
11 import com.ibm.icu.text.DateFormat;
12 import com.ibm.icu.text.DateFormatSymbols;
13 import com.ibm.icu.text.SimpleDateFormat;
14 import com.ibm.icu.util.Calendar;
15 import com.ibm.icu.util.ChineseCalendar;
16 import com.ibm.icu.util.GregorianCalendar;
17 import com.ibm.icu.util.TimeZone;
18 import com.ibm.icu.util.ULocale;
21 * Test of ChineseCalendar.
23 * Leap months in this century:
24 * Wed May 23 2001 = 4638-04*-01, Year 18, Cycle 78
25 * Sun Mar 21 2004 = 4641-02*-01, Year 21, Cycle 78
26 * Thu Aug 24 2006 = 4643-07*-01, Year 23, Cycle 78
27 * Tue Jun 23 2009 = 4646-05*-01, Year 26, Cycle 78
28 * Mon May 21 2012 = 4649-04*-01, Year 29, Cycle 78
29 * Fri Oct 24 2014 = 4651-09*-01, Year 31, Cycle 78
30 * Sun Jul 23 2017 = 4654-06*-01, Year 34, Cycle 78
31 * Sat May 23 2020 = 4657-04*-01, Year 37, Cycle 78
32 * Wed Mar 22 2023 = 4660-02*-01, Year 40, Cycle 78
33 * Fri Jul 25 2025 = 4662-06*-01, Year 42, Cycle 78
34 * Fri Jun 23 2028 = 4665-05*-01, Year 45, Cycle 78
35 * Tue Apr 22 2031 = 4668-03*-01, Year 48, Cycle 78
36 * Thu Dec 22 2033 = 4670-11*-01, Year 50, Cycle 78
37 * Wed Jul 23 2036 = 4673-06*-01, Year 53, Cycle 78
38 * Wed Jun 22 2039 = 4676-05*-01, Year 56, Cycle 78
39 * Sat Mar 22 2042 = 4679-02*-01, Year 59, Cycle 78
40 * Tue Aug 23 2044 = 4681-07*-01, Year 01, Cycle 79
41 * Sun Jun 23 2047 = 4684-05*-01, Year 04, Cycle 79
42 * Thu Apr 21 2050 = 4687-03*-01, Year 07, Cycle 79
43 * Mon Sep 23 2052 = 4689-08*-01, Year 09, Cycle 79
44 * Sat Jul 24 2055 = 4692-06*-01, Year 12, Cycle 79
45 * Wed May 22 2058 = 4695-04*-01, Year 15, Cycle 79
46 * Wed Apr 20 2061 = 4698-03*-01, Year 18, Cycle 79
47 * Fri Aug 24 2063 = 4700-07*-01, Year 20, Cycle 79
48 * Wed Jun 23 2066 = 4703-05*-01, Year 23, Cycle 79
49 * Tue May 21 2069 = 4706-04*-01, Year 26, Cycle 79
50 * Thu Sep 24 2071 = 4708-08*-01, Year 28, Cycle 79
51 * Tue Jul 24 2074 = 4711-06*-01, Year 31, Cycle 79
52 * Sat May 22 2077 = 4714-04*-01, Year 34, Cycle 79
53 * Sat Apr 20 2080 = 4717-03*-01, Year 37, Cycle 79
54 * Mon Aug 24 2082 = 4719-07*-01, Year 39, Cycle 79
55 * Fri Jun 22 2085 = 4722-05*-01, Year 42, Cycle 79
56 * Fri May 21 2088 = 4725-04*-01, Year 45, Cycle 79
57 * Sun Sep 24 2090 = 4727-08*-01, Year 47, Cycle 79
58 * Thu Jul 23 2093 = 4730-06*-01, Year 50, Cycle 79
59 * Tue May 22 2096 = 4733-04*-01, Year 53, Cycle 79
60 * Sun Mar 22 2099 = 4736-02*-01, Year 56, Cycle 79
62 public class ChineseTest extends CalendarTest {
64 public static void main(String args[]) throws Exception {
65 new ChineseTest().run(args);
69 * Test basic mapping to and from Gregorian.
71 public void TestMapping() {
74 // (Note: months are 1-based)
76 1964, 9, 4, 4601, 7,0, 28,
77 1964, 9, 5, 4601, 7,0, 29,
78 1964, 9, 6, 4601, 8,0, 1,
79 1964, 9, 7, 4601, 8,0, 2,
80 1961, 12, 25, 4598, 11,0, 18,
81 1999, 6, 4, 4636, 4,0, 21,
83 1990, 5, 23, 4627, 4,0, 29,
84 1990, 5, 24, 4627, 5,0, 1,
85 1990, 6, 22, 4627, 5,0, 30,
86 1990, 6, 23, 4627, 5,1, 1,
87 1990, 7, 20, 4627, 5,1, 28,
88 1990, 7, 21, 4627, 5,1, 29,
89 1990, 7, 22, 4627, 6,0, 1,
92 ChineseCalendar cal = new ChineseCalendar();
93 StringBuffer buf = new StringBuffer();
95 logln("Gregorian -> Chinese");
96 //java.util.Calendar grego = java.util.Calendar.getInstance();
97 Calendar grego = Calendar.getInstance();
99 for (int i=0; i<DATA.length; ) {
100 grego.set(DATA[i++], DATA[i++]-1, DATA[i++]);
101 Date date = grego.getTime();
103 int y = cal.get(Calendar.EXTENDED_YEAR);
104 int m = cal.get(Calendar.MONTH)+1; // 0-based -> 1-based
105 int L = cal.get(Calendar.IS_LEAP_MONTH);
106 int d = cal.get(Calendar.DAY_OF_MONTH);
107 int yE = DATA[i++]; // Expected y, m, isLeapMonth, d
108 int mE = DATA[i++]; // 1-based
112 buf.append(date + " -> ");
113 buf.append(y + "/" + m + (L==1?"(leap)":"") + "/" + d);
114 if (y == yE && m == mE && L == LE && d == dE) {
115 logln("OK: " + buf.toString());
117 errln("Fail: " + buf.toString() + ", expected " +
118 yE + "/" + mE + (LE==1?"(leap)":"") + "/" + dE);
122 logln("Chinese -> Gregorian");
123 for (int i=0; i<DATA.length; ) {
124 grego.set(DATA[i++], DATA[i++]-1, DATA[i++]);
125 Date dexp = grego.getTime();
126 int cyear = DATA[i++];
127 int cmonth = DATA[i++];
128 int cisleapmonth = DATA[i++];
129 int cdayofmonth = DATA[i++];
131 cal.set(Calendar.EXTENDED_YEAR, cyear);
132 cal.set(Calendar.MONTH, cmonth-1);
133 cal.set(Calendar.IS_LEAP_MONTH, cisleapmonth);
134 cal.set(Calendar.DAY_OF_MONTH, cdayofmonth);
135 Date date = cal.getTime();
137 buf.append(cyear + "/" + cmonth +
138 (cisleapmonth==1?"(leap)":"") + "/" + cdayofmonth);
139 buf.append(" -> " + date);
140 if (date.equals(dexp)) {
141 logln("OK: " + buf.toString());
143 errln("Fail: " + buf.toString() + ", expected " + dexp);
149 * Make sure no Gregorian dates map to Chinese 1-based day of
150 * month zero. This was a problem with some of the astronomical
151 * new moon determinations.
153 public void TestZeroDOM() {
154 ChineseCalendar cal = new ChineseCalendar();
155 GregorianCalendar greg = new GregorianCalendar(1989, Calendar.SEPTEMBER, 1);
156 logln("Start: " + greg.getTime());
157 for (int i=0; i<1000; ++i) {
158 cal.setTimeInMillis(greg.getTimeInMillis());
159 if (cal.get(Calendar.DAY_OF_MONTH) == 0) {
160 errln("Fail: " + greg.getTime() + " -> " +
161 cal.get(Calendar.EXTENDED_YEAR) + "/" +
162 cal.get(Calendar.MONTH) +
163 (cal.get(Calendar.IS_LEAP_MONTH)==1?"(leap)":"") +
164 "/" + cal.get(Calendar.DAY_OF_MONTH));
166 greg.add(Calendar.DAY_OF_YEAR, 1);
168 logln("End: " + greg.getTime());
172 * Test minimum and maximum functions.
174 public void TestLimits() {
175 // The number of days and the start date can be adjusted
176 // arbitrarily to either speed up the test or make it more
177 // thorough, but try to test at least a full year, preferably a
178 // full non-leap and a full leap year.
180 // Final parameter is either number of days, if > 0, or test
181 // duration in seconds, if < 0.
182 java.util.Calendar tempcal = java.util.Calendar.getInstance();
184 tempcal.set(1989, Calendar.NOVEMBER, 1);
185 ChineseCalendar chinese = new ChineseCalendar();
186 doLimitsTest(chinese, null, tempcal.getTime());
187 doTheoreticalLimitsTest(chinese, true);
191 * Run through several standard tests from Dershowitz & Reingold.
193 public void TestJulianDayMapping() {
195 final TestCase[] tests = {
197 // From Dershowitz & Reingold, "Calendrical Calculations".
199 // The months in this table are 1-based rather than 0-based.
201 // * Failing fields->millis
202 // ** Millis->fields gives 0-based month -1
203 // These failures were fixed by changing the start search date
204 // for the winter solstice from Dec 15 to Dec 1.
206 // Julian Day Era Year Month Leap DOM WkDay
207 new ChineseTestCase(1507231.5, 35, 11, 6, false, 12, SUN),
208 new ChineseTestCase(1660037.5, 42, 9, 10, false, 27, WED),
209 new ChineseTestCase(1746893.5, 46, 7, 8, false, 4, WED),
210 new ChineseTestCase(1770641.5, 47, 12, 8, false, 9, SUN),
211 new ChineseTestCase(1892731.5, 52, 46, 11, false, 20, WED),
212 new ChineseTestCase(1931579.5, 54, 33, 4, false, 5, MON),
213 new ChineseTestCase(1974851.5, 56, 31, 10, false, 15, SAT),
214 new ChineseTestCase(2091164.5, 61, 50, 3, false, 7, SUN),
215 new ChineseTestCase(2121509.5, 63, 13, 4, false, 24, SUN),
216 new ChineseTestCase(2155779.5, 64, 47, 2, false, 9, FRI),
217 new ChineseTestCase(2174029.5, 65, 37, 2, false, 9, SAT),
218 new ChineseTestCase(2191584.5, 66, 25, 2, false, 23, FRI),
219 new ChineseTestCase(2195261.5, 66, 35, 3, false, 9, SUN), //*
220 new ChineseTestCase(2229274.5, 68, 8, 5, false, 2, SUN), //*
221 new ChineseTestCase(2245580.5, 68, 53, 1, false, 8, WED), //**
222 new ChineseTestCase(2266100.5, 69, 49, 3, false, 4, SAT),
223 new ChineseTestCase(2288542.5, 70, 50, 8, false, 2, SAT), //*
224 new ChineseTestCase(2290901.5, 70, 57, 1, false, 29, SAT), //*
225 new ChineseTestCase(2323140.5, 72, 25, 4, true, 20, WED), //*
226 new ChineseTestCase(2334848.5, 72, 57, 6, false, 5, SUN),
227 new ChineseTestCase(2348020.5, 73, 33, 6, false, 6, FRI),
228 new ChineseTestCase(2366978.5, 74, 25, 5, false, 5, SUN),
229 new ChineseTestCase(2385648.5, 75, 16, 6, false, 12, MON),
230 new ChineseTestCase(2392825.5, 75, 36, 2, false, 13, WED),
231 new ChineseTestCase(2416223.5, 76, 40, 3, false, 22, SUN),
232 new ChineseTestCase(2425848.5, 77, 6, 7, false, 21, SUN),
233 new ChineseTestCase(2430266.5, 77, 18, 8, false, 9, MON),
234 new ChineseTestCase(2430833.5, 77, 20, 3, false, 15, MON),
235 new ChineseTestCase(2431004.5, 77, 20, 9, false, 9, THU),
236 new ChineseTestCase(2448698.5, 78, 9, 2, false, 14, TUE),
237 new ChineseTestCase(2450138.5, 78, 13, 1, false, 7, SUN),
238 new ChineseTestCase(2465737.5, 78, 55, 10, false, 14, WED),
239 new ChineseTestCase(2486076.5, 79, 51, 6, false, 7, SUN),
241 // Additional tests not from D&R
242 new ChineseTestCase(2467496.5, 78, 60, 8, false, 2, FRI), // year 60
245 ChineseCalendar cal = new ChineseCalendar();
246 cal.setLenient(true);
247 doTestCases(tests, cal);
252 * Q: Why is this in Calendar tests instead of Format tests?
253 * Note: This test assumes that Chinese calendar formatted dates can be parsed
254 * unambiguously to recover the original Date that was formatted. This is not
255 * currently true since Chinese calendar formatted dates do not include an era.
256 * To address this will require formatting/parsing of fields from some other
257 * associated calendar, as per ICU ticket #9043. This test should be timebombed
258 * until that ticket is addressed.
260 public void TestFormat() {
261 ChineseCalendar cal = new ChineseCalendar();
262 DateFormat fmt = DateFormat.getDateTimeInstance(cal,
263 DateFormat.DEFAULT, DateFormat.DEFAULT);
265 java.util.Calendar tempcal = java.util.Calendar.getInstance();
268 Date[] DATA = new Date[2];
269 tempcal.set(2001, Calendar.MAY, 22);
270 DATA[0] = tempcal.getTime();
271 tempcal.set(2001, Calendar.MAY, 23);
272 DATA[1] = tempcal.getTime();
273 // Wed May 23 2001 = Month 4(leap), Day 1, Year 18, Cycle 78
275 for (int i=0; i<DATA.length; ++i) {
276 String s = fmt.format(DATA[i]);
278 Date e = fmt.parse(s);
279 if (e.equals(DATA[i])) {
280 logln("Ok: " + DATA[i] + " -> " + s + " -> " + e);
281 } else if (logKnownIssue("9043", "Ambiguous Chinese era parsing")) {
282 logln("Ambiguous parse fails: " + DATA[i] + " -> " + s + " -> " + e);
284 errln("FAIL: " + DATA[i] + " -> " + s + " -> " + e);
286 } catch (java.text.ParseException e) {
287 errln("Fail: " + s + " -> parse failure at " + e.getErrorOffset());
294 * Make sure IS_LEAP_MONTH participates in field resolution.
296 public void TestResolution() {
297 ChineseCalendar cal = new ChineseCalendar();
298 DateFormat fmt = DateFormat.getDateInstance(cal, DateFormat.DEFAULT);
300 // May 22 2001 = y4638 m4 d30 doy119
301 // May 23 2001 = y4638 m4* d1 doy120
303 final int THE_YEAR = 4638;
308 // (field, value)+, END, exp.month, exp.isLeapMonth, exp.DOM
309 // Note: exp.month is ONE-BASED
311 // If we set DAY_OF_YEAR only, that should be used
312 Calendar.DAY_OF_YEAR, 1,
316 // If we set MONTH only, that should be used
317 Calendar.IS_LEAP_MONTH, 1,
318 Calendar.DAY_OF_MONTH, 1,
321 4,1,1, // Expect 4*-1
323 // If we set the DOY last, that should take precedence
324 Calendar.MONTH, 1, // Should ignore
325 Calendar.IS_LEAP_MONTH, 1, // Should ignore
326 Calendar.DAY_OF_MONTH, 1, // Should ignore
327 Calendar.DAY_OF_YEAR, 121,
329 4,1,2, // Expect 4*-2
331 // I've disabled this test because it doesn't work this way,
332 // not even with a GregorianCalendar! MONTH alone isn't enough
333 // to supersede DAY_OF_YEAR. Some other month-related field is
334 // also required. - Liu 11/28/00
335 //! // If we set MONTH last, that should take precedence
336 //! ChineseCalendar.IS_LEAP_MONTH, 1,
337 //! Calendar.DAY_OF_MONTH, 1,
338 //! Calendar.DAY_OF_YEAR, 5, // Should ignore
339 //! Calendar.MONTH, 3,
341 //! 4,1,1, // Expect 4*-1
343 // If we set IS_LEAP_MONTH last, that should take precedence
345 Calendar.DAY_OF_MONTH, 1,
346 Calendar.DAY_OF_YEAR, 5, // Should ignore
347 Calendar.IS_LEAP_MONTH, 1,
349 4,1,1, // Expect 4*-1
352 StringBuffer buf = new StringBuffer();
353 for (int i=0; i<DATA.length; ) {
355 cal.set(Calendar.EXTENDED_YEAR, THE_YEAR);
357 buf.append("EXTENDED_YEAR=" + THE_YEAR);
358 while (DATA[i] != END) {
359 cal.set(DATA[i++], DATA[i++]);
360 buf.append(" " + fieldName(DATA[i-2]) + "=" + DATA[i-1]);
362 ++i; // Skip over END mark
363 int expMonth = DATA[i++]-1;
364 int expIsLeapMonth = DATA[i++];
365 int expDOM = DATA[i++];
366 int month = cal.get(Calendar.MONTH);
367 int isLeapMonth = cal.get(Calendar.IS_LEAP_MONTH);
368 int dom = cal.get(Calendar.DAY_OF_MONTH);
369 if (expMonth == month && expIsLeapMonth == isLeapMonth &&
371 logln("OK: " + buf + " => " + fmt.format(cal.getTime()));
373 String s = fmt.format(cal.getTime());
375 cal.set(Calendar.EXTENDED_YEAR, THE_YEAR);
376 cal.set(Calendar.MONTH, expMonth);
377 cal.set(Calendar.IS_LEAP_MONTH, expIsLeapMonth);
378 cal.set(Calendar.DAY_OF_MONTH, expDOM);
379 errln("Fail: " + buf + " => " + s +
380 "=" + (month+1) + "," + isLeapMonth + "," + dom +
381 ", expected " + fmt.format(cal.getTime()) +
382 "=" + (expMonth+1) + "," + expIsLeapMonth + "," + expDOM);
388 * Test the behavior of fields that are out of range.
390 public void TestOutOfRange() {
391 int[] DATA = new int[] {
393 4638, 13, 1, 4639, 1, 1,
394 4638, 18, 1, 4639, 6, 1,
395 4639, 0, 1, 4638, 12, 1,
396 4639, -6, 1, 4638, 6, 1,
397 4638, 1, 32, 4638, 2, 2, // 1-4638 has 30 days
398 4638, 2, -1, 4638, 1, 29,
400 ChineseCalendar cal = new ChineseCalendar();
401 for (int i=0; i<DATA.length; ) {
403 int m1 = DATA[i++]-1;
406 int m2 = DATA[i++]-1;
409 cal.set(Calendar.EXTENDED_YEAR, y1);
412 int y = cal.get(Calendar.EXTENDED_YEAR);
413 int m = cal.get(MONTH);
414 int d = cal.get(DATE);
415 if (y!=y2 || m!=m2 || d!=d2) {
416 errln("Fail: " + y1 + "/" + (m1+1) + "/" + d1 + " resolves to " +
417 y + "/" + (m+1) + "/" + d + ", expected " +
418 y2 + "/" + (m2+1) + "/" + d2);
419 } else if (isVerbose()) {
420 logln("OK: " + y1 + "/" + (m1+1) + "/" + d1 + " resolves to " +
421 y + "/" + (m+1) + "/" + d);
427 * Test the behavior of ChineseCalendar.add(). The only real
428 * nastiness with roll is the MONTH field around leap months.
430 public void TestAdd() {
431 int[][] tests = new int[][] {
432 // MONTHS ARE 1-BASED HERE
434 // year mon day field amount year mon day
435 { 4642, 3,0, 15, MONTH, 3, 4642, 6,0, 15 }, // normal
436 { 4639, 12,0, 15, MONTH, 1, 4640, 1,0, 15 }, // across year
437 { 4640, 1,0, 15, MONTH, -1, 4639, 12,0, 15 }, // across year
438 { 4638, 3,0, 15, MONTH, 3, 4638, 5,0, 15 }, // 4=leap
439 { 4638, 3,0, 15, MONTH, 2, 4638, 4,1, 15 }, // 4=leap
440 { 4638, 4,0, 15, MONTH, 1, 4638, 4,1, 15 }, // 4=leap
441 { 4638, 4,1, 15, MONTH, 1, 4638, 5,0, 15 }, // 4=leap
442 { 4638, 4,0, 30, MONTH, 1, 4638, 4,1, 29 }, // dom should pin
443 { 4638, 4,0, 30, MONTH, 2, 4638, 5,0, 30 }, // no dom pin
444 { 4638, 4,0, 30, MONTH, 3, 4638, 6,0, 29 }, // dom should pin
447 ChineseCalendar cal = new ChineseCalendar();
448 doRollAdd(ADD, cal, tests);
452 * Test the behavior of ChineseCalendar.roll(). The only real
453 * nastiness with roll is the MONTH field around leap months.
455 public void TestRoll() {
456 int[][] tests = new int[][] {
457 // MONTHS ARE 1-BASED HERE
459 // year mon day field amount year mon day
460 { 4642, 3,0, 15, MONTH, 3, 4642, 6,0, 15 }, // normal
461 { 4642, 3,0, 15, MONTH, 11, 4642, 2,0, 15 }, // normal
462 { 4639, 12,0, 15, MONTH, 1, 4639, 1,0, 15 }, // across year
463 { 4640, 1,0, 15, MONTH, -1, 4640, 12,0, 15 }, // across year
464 { 4638, 3,0, 15, MONTH, 3, 4638, 5,0, 15 }, // 4=leap
465 { 4638, 3,0, 15, MONTH, 16, 4638, 5,0, 15 }, // 4=leap
466 { 4638, 3,0, 15, MONTH, 2, 4638, 4,1, 15 }, // 4=leap
467 { 4638, 3,0, 15, MONTH, 28, 4638, 4,1, 15 }, // 4=leap
468 { 4638, 4,0, 15, MONTH, 1, 4638, 4,1, 15 }, // 4=leap
469 { 4638, 4,0, 15, MONTH, -12, 4638, 4,1, 15 }, // 4=leap
470 { 4638, 4,1, 15, MONTH, 1, 4638, 5,0, 15 }, // 4=leap
471 { 4638, 4,1, 15, MONTH, -25, 4638, 5,0, 15 }, // 4=leap
472 { 4638, 4,0, 30, MONTH, 1, 4638, 4,1, 29 }, // dom should pin
473 { 4638, 4,0, 30, MONTH, 14, 4638, 4,1, 29 }, // dom should pin
474 { 4638, 4,0, 30, MONTH, 15, 4638, 5,0, 30 }, // no dom pin
475 { 4638, 4,0, 30, MONTH, -10, 4638, 6,0, 29 }, // dom should pin
478 ChineseCalendar cal = new ChineseCalendar();
479 doRollAdd(ROLL, cal, tests);
482 void doRollAdd(boolean roll, ChineseCalendar cal, int[][] tests) {
483 String name = roll ? "rolling" : "adding";
485 for (int i = 0; i < tests.length; i++) {
486 int[] test = tests[i];
489 cal.set(Calendar.EXTENDED_YEAR, test[0]);
490 cal.set(Calendar.MONTH, test[1]-1);
491 cal.set(Calendar.IS_LEAP_MONTH, test[2]);
492 cal.set(Calendar.DAY_OF_MONTH, test[3]);
494 cal.roll(test[4], test[5]);
496 cal.add(test[4], test[5]);
498 if (cal.get(Calendar.EXTENDED_YEAR) != test[6] ||
499 cal.get(MONTH) != (test[7]-1) ||
500 cal.get(Calendar.IS_LEAP_MONTH) != test[8] ||
501 cal.get(DATE) != test[9]) {
502 errln("Fail: " + name + " " +
503 ymdToString(test[0], test[1]-1, test[2], test[3])
504 + " " + fieldName(test[4]) + " by " + test[5]
506 ymdToString(test[6], test[7]-1, test[8], test[9])
507 + ", got " + ymdToString(cal));
508 } else if (isVerbose()) {
509 logln("OK: " + name + " " +
510 ymdToString(test[0], test[1]-1, test[2], test[3])
511 + " " + fieldName(test[4]) + " by " + test[5]
512 + ": got " + ymdToString(cal));
518 * Convert year,month,day values to the form "year/month/day".
519 * On input the month value is zero-based, but in the result string it is one-based.
521 static public String ymdToString(int year, int month, int isLeapMonth, int day) {
522 return "" + year + "/" + (month+1) +
523 ((isLeapMonth!=0)?"(leap)":"") +
527 // public void TestFindLeapMonths() {
528 // ChineseCalendar cal = new ChineseCalendar();
529 // cal.setTime(new Date(2000-1900, Calendar.JANUARY, 1));
530 // long end = new Date(2100-1900, Calendar.JANUARY, 1).getTime();
531 // ChineseDateFormat fmt = (ChineseDateFormat) DateFormat.getInstance(cal);
532 // fmt.applyPattern("u-MMl-dd, 'Year' y, 'Cycle' G");
533 // while (cal.getTimeInMillis() < end) {
534 // if (cal.get(ChineseCalendar.IS_LEAP_MONTH) != 0) {
535 // cal.set(Calendar.DAY_OF_MONTH, 1);
536 // logln(cal.getTime() + " = " + fmt.format(cal.getTime()));
537 // cal.set(Calendar.DAY_OF_MONTH, 29);
539 // cal.add(Calendar.DAY_OF_YEAR, 25);
543 public void TestCoverage() {
544 // Coverage for constructors
546 // new ChineseCalendar(Date)
547 ChineseCalendar cal = new ChineseCalendar(new Date());
549 errln("could not create ChineseCalendar with Date");
554 // new ChineseCalendar(int year, int month, int isLeapMonth, int date)
555 ChineseCalendar cal = new ChineseCalendar(23, Calendar.JULY, 1, 2);
557 errln("could not create ChineseCalendar with year,month,isLeapMonth,date");
559 // Make sure the given values are properly set
560 if (cal.get(Calendar.YEAR) != 23 || cal.get(Calendar.MONTH) != Calendar.JULY
561 || cal.get(Calendar.IS_LEAP_MONTH) != 1 || cal.get(Calendar.DATE) != 2
562 || cal.get(Calendar.MILLISECONDS_IN_DAY) != 0) {
563 errln("ChineseCalendar was initialized incorrectly with year,month,isLeapMonth,date");
568 // new ChineseCalendar(int year, int month, int isLeapMonth, int date, int hour, int minute, int second)
569 ChineseCalendar cal = new ChineseCalendar(23, Calendar.JULY, 1, 2, 12, 34, 56);
571 errln("could not create ChineseCalendar with year,month,isLeapMonth,date,hour,minute,second");
573 // Make sure the given values are properly set
574 if (cal.get(Calendar.YEAR) != 23 || cal.get(Calendar.MONTH) != Calendar.JULY
575 || cal.get(Calendar.IS_LEAP_MONTH) != 1 || cal.get(Calendar.DATE) != 2
576 || cal.get(Calendar.HOUR_OF_DAY) != 12 || cal.get(Calendar.MINUTE) != 34
577 || cal.get(Calendar.SECOND) != 56 || cal.get(Calendar.MILLISECOND) != 0) {
578 errln("ChineseCalendar was initialized incorrectly with year,month,isLeapMonth,date,hour,minute,second");
583 // new ChineseCalendar(Locale)
584 ChineseCalendar cal = new ChineseCalendar(Locale.getDefault());
586 errln("could not create ChineseCalendar with Locale");
591 // new ChineseCalendar(ULocale)
592 ChineseCalendar cal = new ChineseCalendar(ULocale.getDefault());
594 errln("could not create ChineseCalendar with ULocale");
600 // new ChineseCalendar(TimeZone)
601 ChineseCalendar cal = new ChineseCalendar(TimeZone.getDefault());
603 errln("could not create ChineseCalendar with TimeZone");
608 // new ChineseCalendar(TimeZone, Locale)
609 ChineseCalendar cal = new ChineseCalendar(TimeZone.getDefault(), Locale.getDefault());
611 errln("could not create ChineseCalendar with TimeZone,Locale");
616 // new ChineseCalendar(TimeZone, ULocale)
617 ChineseCalendar cal = new ChineseCalendar(TimeZone.getDefault(), ULocale.getDefault());
619 errln("could not create ChineseCalendar with TimeZone,ULocale");
623 // Note: ICU 50 or later versions, DateFormat.getInstance(ChineseCalendar) no longer
624 // returns an instance of ChineseDateFormat. Chinese calendar formatting support was
625 // changed and integrated into SimpleDateFormat since ICU 49. Also, ChineseDateFormat
626 // specific pattern letter "l" is no longer used by the new implementation.
628 // ChineseCalendar cal = new ChineseCalendar();
629 // DateFormat format = DateFormat.getInstance(cal);
630 // if(!(format instanceof ChineseDateFormat)){
631 // errln("DateFormat.getInstance("+cal+") did not return a ChineseDateFormat");
633 // ChineseDateFormat fmt = (ChineseDateFormat)format;
634 // fmt.applyPattern("llyyll");
635 // Date time = getDate(2100, Calendar.JANUARY, 1);
636 // String str = fmt.format(time);
638 // Date e = fmt.parse(str);
639 // logln("chinese calendar time: " + time + " result: " + str + " --> " + e);
640 // } catch (java.text.ParseException ex) {
641 // logln(ex.getMessage()); // chinese calendar can't parse this, no error for now
644 //new ChineseCalendar(TimeZone,ULocale)
645 ChineseCalendar ccal2 = new ChineseCalendar(TimeZone.getDefault(),
648 errln("could not create ChineseCalendar with TimeZone ULocale");
650 DateFormat fmt2 = DateFormat.getDateInstance(ccal2, DateFormat.DEFAULT, ULocale.CHINA);
651 Date time2 = getDate(2001, Calendar.MAY, 23);
652 String str2 = fmt2.format(time2);
653 logln("Chinese calendar time: " + time2 + " result: " + str2);
656 public void TestScratch(){
657 String[] strMonths = {"Januari", "Pebruari", "Maret", "April", "Mei", "Juni",
658 "Juli", "Agustus", "September", "Oktober", "Nopember", "Desember"};
659 String[] strShortMonths = {"Jan", "Peb", "Mar", "Apr", "Mei", "Jun",
660 "Jul", "Agt", "Sep", "Okt", "Nop", "Des"};
661 String[] strWeeks = {"", "Minggu", "Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu"};
662 DateFormatSymbols dfsDate = new DateFormatSymbols(new Locale("id", "ID"));
663 dfsDate.setMonths(strMonths);
664 dfsDate.setShortMonths(strShortMonths);
665 dfsDate.setWeekdays(strWeeks);
666 ULocale uloInd = dfsDate.getLocale(ULocale.ACTUAL_LOCALE);
668 errln("did not get the expected ULocale");
670 logln(uloInd.toString());
671 Locale locInd = uloInd.toLocale();
673 errln("did not get the expected result");
675 logln(locInd.toString());
678 public void TestInitWithCurrentTime() {
680 // if the chinese calendar current millis isn't called, the default year is wrong.
681 // this test is assuming the 'year' is the current cycle
682 // so when we cross a cycle boundary, the target will need to change
683 // that shouldn't be for awhile yet...
685 ChineseCalendar cc = new ChineseCalendar();
686 cc.set(Calendar.YEAR, 22);
687 cc.set(Calendar.MONTH, 0);
688 // need to set leap month flag off, otherwise, the test case always fails when
689 // current time is in a leap month
690 cc.set(Calendar.IS_LEAP_MONTH, 0);
691 cc.set(Calendar.DATE, 19);
692 cc.set(Calendar.HOUR_OF_DAY, 0);
693 cc.set(Calendar.MINUTE, 0);
694 cc.set(Calendar.SECOND, 0);
695 cc.set(Calendar.MILLISECOND, 0);
697 cc.add(Calendar.DATE, 1);
699 Calendar cal = new GregorianCalendar(2005, Calendar.FEBRUARY, 28);
700 Date target = cal.getTime();
701 Date result = cc.getTime();
703 assertEquals("chinese and gregorian date should match", target, result);
706 public void Test6510()
708 Calendar gregorianCalendar;
709 ChineseCalendar chineseCalendar, chineseCalendar2;
710 ChineseDateFormat dateFormat;
711 SimpleDateFormat simpleDateFormat;
713 simpleDateFormat = new com.ibm.icu.text.SimpleDateFormat("MM/dd/yyyy G 'at' HH:mm:ss vvvv", Locale.US);
714 dateFormat = new com.ibm.icu.text.ChineseDateFormat("MM/dd/yyyy(G) HH:mm:ss", Locale.CHINA);
716 // lunar to gregorian
717 chineseCalendar = new ChineseCalendar(77, 26, Calendar.JANUARY, 0, 6, 0, 0, 0);
718 gregorianCalendar = Calendar.getInstance(Locale.US);
719 gregorianCalendar.setTime(chineseCalendar.getTime());
721 // gregorian to lunar
722 chineseCalendar2 = new ChineseCalendar();
723 chineseCalendar2.setTimeInMillis(gregorianCalendar.getTimeInMillis());
725 // validate roundtrip
726 if (chineseCalendar.getTimeInMillis() != chineseCalendar2.getTimeInMillis())
728 errln("time1: " + chineseCalendar.getTimeInMillis());
729 errln("time2: " + chineseCalendar2.getTimeInMillis());
730 errln("Lunar [MM/dd/y(G) HH:mm:ss] " + dateFormat.format(chineseCalendar));
731 errln("**PROBLEM Grego [MM/dd/y(G) HH:mm:ss] " + simpleDateFormat.format(gregorianCalendar));
732 errln("Grego [MM/dd/y(G) HH:mm:ss] " + simpleDateFormat.format(gregorianCalendar));
733 errln("Lunar [MM/dd/y(G) HH:mm:ss] " + dateFormat.format(chineseCalendar2));