]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-52_1/main/tests/core/src/com/ibm/icu/dev/test/calendar/DangiTest.java
Clean up imports.
[Dictionary.git] / jars / icu4j-52_1 / main / tests / core / src / com / ibm / icu / dev / test / calendar / DangiTest.java
1 /*
2  *******************************************************************************
3  * Copyright (C) 2012, International Business Machines Corporation and         *
4  * others. All Rights Reserved.                                                *
5  *******************************************************************************
6  */
7 package com.ibm.icu.dev.test.calendar;
8 import java.util.Date;
9
10 import com.ibm.icu.text.DateFormat;
11 import com.ibm.icu.util.Calendar;
12 import com.ibm.icu.util.DangiCalendar;
13 import com.ibm.icu.util.GregorianCalendar;
14 import com.ibm.icu.util.TimeZone;
15 import com.ibm.icu.util.ULocale;
16
17 public class DangiTest extends CalendarTest {
18
19     public static void main(String args[]) throws Exception {
20         new DangiTest().run(args);
21     }
22
23     /**
24      * Test basic mapping to and from Gregorian.
25      */
26     public void TestMapping() {
27         final int[] DATA = {
28             // (Note: months are 1-based)
29             // Gregorian    Korean (Dan-gi)
30             1964,  9,  4,   4297,  7,0, 28,
31             1964,  9,  5,   4297,  7,0, 29,
32             1964,  9,  6,   4297,  8,0,  1,
33             1964,  9,  7,   4297,  8,0,  2,
34             1961, 12, 25,   4294, 11,0, 18,
35             1999,  6,  4,   4332,  4,0, 21,
36             
37             1990,  5, 23,   4323,  4,0, 29,
38             1990,  5, 24,   4323,  5,0,  1,
39             1990,  6, 22,   4323,  5,0, 30,
40             1990,  6, 23,   4323,  5,1,  1,
41             1990,  7, 20,   4323,  5,1, 28,
42             1990,  7, 21,   4323,  5,1, 29,
43             1990,  7, 22,   4323,  6,0,  1,
44
45             // Some tricky dates (where GMT+8 doesn't agree with GMT+9)
46             //
47             // The list is from http://www.math.snu.ac.kr/~kye/others/lunar.html ('kye ref').
48             // However, for some dates disagree with the above reference so KASI's
49             // calculation was cross-referenced:
50             //  http://astro.kasi.re.kr/Life/ConvertSolarLunarForm.aspx?MenuID=115
51             1880, 11,  3,   4213, 10,0,  1, // astronomer's GMT+8 / KASI disagrees with the kye ref
52             1882, 12, 10,   4215, 11,0,  1,
53             1883,  7, 4,    4216,  6,0,  1,
54             1884,  4, 25,   4217,  4,0,  1,
55             1885,  5, 14,   4218,  4,0,  1,
56             1891,  1, 10,   4223, 12,0,  1,
57             1893,  4, 16,   4226,  3,0,  1,
58             1894,  5,  5,   4227,  4,0,  1,
59             1897,  7, 29,   4230,  7,0,  1, // astronomer's GMT+8 disagrees with all other ref (looks like our astronomer's error, see ad hoc fix at ChineseCalendar::getTimezoneOffset)
60             1903, 10, 20,   4236,  9,0,  1,
61             1904,  1, 17,   4236, 12,0,  1,
62             1904, 11,  7,   4237, 10,0,  1,
63             1905,  5,  4,   4238,  4,0,  1,
64             1907,  7, 10,   4240,  6,0,  1,
65             1908,  4, 30,   4241,  4,0,  1,
66             1908,  9, 25,   4241,  9,0,  1,
67             1909,  9, 14,   4242,  8,0,  1,
68             1911, 12, 20,   4244, 11,0,  1,
69             1976, 11, 22,   4309, 10,0,  1,
70         };
71
72         Calendar cal = Calendar.getInstance(new ULocale("ko_KR@calendar=dangi"));
73         StringBuilder buf = new StringBuilder();
74
75         logln("Gregorian -> Korean Lunar (Dangi)");
76
77         Calendar grego = Calendar.getInstance();
78         grego.clear();
79         for (int i = 0; i < DATA.length;) {
80             grego.set(DATA[i++], DATA[i++] - 1, DATA[i++]);
81             Date date = grego.getTime();
82             cal.setTime(date);
83             int y = cal.get(Calendar.EXTENDED_YEAR);
84             int m = cal.get(Calendar.MONTH) + 1; // 0-based -> 1-based
85             int L = cal.get(Calendar.IS_LEAP_MONTH);
86             int d = cal.get(Calendar.DAY_OF_MONTH);
87             int yE = DATA[i++]; // Expected y, m, isLeapMonth, d
88             int mE = DATA[i++]; // 1-based
89             int LE = DATA[i++];
90             int dE = DATA[i++];
91             buf.setLength(0);
92             buf.append(date + " -> ");
93             buf.append(y + "/" + m + (L == 1 ? "(leap)" : "") + "/" + d);
94             if (y == yE && m == mE && L == LE && d == dE) {
95                 logln("OK: " + buf.toString());
96             } else {
97                 errln("Fail: " + buf.toString() + ", expected " + yE + "/" + mE + (LE == 1 ? "(leap)" : "") + "/" + dE);
98             }
99         }
100
101         logln("Korean Lunar (Dangi) -> Gregorian");
102         for (int i = 0; i < DATA.length;) {
103             grego.set(DATA[i++], DATA[i++] - 1, DATA[i++]);
104             Date dexp = grego.getTime();
105             int cyear = DATA[i++];
106             int cmonth = DATA[i++];
107             int cisleapmonth = DATA[i++];
108             int cdayofmonth = DATA[i++];
109             cal.clear();
110             cal.set(Calendar.EXTENDED_YEAR, cyear);
111             cal.set(Calendar.MONTH, cmonth - 1);
112             cal.set(Calendar.IS_LEAP_MONTH, cisleapmonth);
113             cal.set(Calendar.DAY_OF_MONTH, cdayofmonth);
114             Date date = cal.getTime();
115             buf.setLength(0);
116             buf.append(cyear + "/" + cmonth + (cisleapmonth == 1 ? "(leap)" : "") + "/" + cdayofmonth);
117             buf.append(" -> " + date);
118             if (date.equals(dexp)) {
119                 logln("OK: " + buf.toString());
120             } else {
121                 errln("Fail: " + buf.toString() + ", expected " + dexp);
122             }
123         }
124     }
125
126     /**
127      * Make sure no Gregorian dates map to Chinese 1-based day of
128      * month zero.  This was a problem with some of the astronomical
129      * new moon determinations.
130      */
131     public void TestZeroDOM() {
132         Calendar cal = Calendar.getInstance(new ULocale("ko_KR@calendar=dangi"));
133         GregorianCalendar greg = new GregorianCalendar(1989, Calendar.SEPTEMBER, 1);
134         logln("Start: " + greg.getTime());
135         for (int i=0; i<1000; ++i) {
136             cal.setTimeInMillis(greg.getTimeInMillis());
137             if (cal.get(Calendar.DAY_OF_MONTH) == 0) {
138                 errln("Fail: " + greg.getTime() + " -> " +
139                       cal.get(Calendar.YEAR) + "/" +
140                       cal.get(Calendar.MONTH) +
141                       (cal.get(Calendar.IS_LEAP_MONTH)==1?"(leap)":"") +
142                       "/" + cal.get(Calendar.DAY_OF_MONTH));
143             }
144             greg.add(Calendar.DAY_OF_YEAR, 1);
145         }
146         logln("End: " + greg.getTime());
147     }
148
149     /**
150      * Test minimum and maximum functions.
151      */
152     public void TestLimits() {
153         // The number of days and the start date can be adjusted
154         // arbitrarily to either speed up the test or make it more
155         // thorough, but try to test at least a full year, preferably a
156         // full non-leap and a full leap year.
157
158         // Final parameter is either number of days, if > 0, or test
159         // duration in seconds, if < 0.
160         Calendar tempcal = Calendar.getInstance();
161         tempcal.clear();
162         tempcal.set(1989, Calendar.NOVEMBER, 1);
163         Calendar dangi = Calendar.getInstance(new ULocale("ko_KR@calendar=dangi"));
164         doLimitsTest(dangi, null, tempcal.getTime());
165         doTheoreticalLimitsTest(dangi, true);
166     }
167
168     /**
169      * Make sure IS_LEAP_MONTH participates in field resolution.
170      */
171     public void TestResolution() {
172         Calendar cal = Calendar.getInstance(new ULocale("ko_KR@calendar=dangi"));
173         DateFormat fmt = DateFormat.getDateInstance(cal, DateFormat.DEFAULT);
174
175         // May 22 4334 = y4334 m4 d30 doy119
176         // May 23 4334 = y4334 m4* d1 doy120
177
178         final int THE_YEAR = 4334;
179         final int END = -1;
180
181         int[] DATA = {
182             // Format:
183             // (field, value)+, END, exp.month, exp.isLeapMonth, exp.DOM
184             // Note: exp.month is ONE-BASED
185
186             // If we set DAY_OF_YEAR only, that should be used
187             Calendar.DAY_OF_YEAR, 1,
188             END,
189             1,0,1, // Expect 1-1
190             
191             // If we set MONTH only, that should be used
192             Calendar.IS_LEAP_MONTH, 1,
193             Calendar.DAY_OF_MONTH, 1,
194             Calendar.MONTH, 3,
195             END,
196             4,1,1, // Expect 4*-1
197             
198             // If we set the DOY last, that should take precedence
199             Calendar.MONTH, 1, // Should ignore
200             Calendar.IS_LEAP_MONTH, 1, // Should ignore
201             Calendar.DAY_OF_MONTH, 1, // Should ignore
202             Calendar.DAY_OF_YEAR, 121,
203             END,
204             4,1,2, // Expect 4*-2
205             
206             // If we set IS_LEAP_MONTH last, that should take precedence
207             Calendar.MONTH, 3,
208             Calendar.DAY_OF_MONTH, 1,
209             Calendar.DAY_OF_YEAR, 5, // Should ignore
210             Calendar.IS_LEAP_MONTH, 1,
211             END,
212             4,1,1, // Expect 4*-1
213         };
214
215         StringBuilder buf = new StringBuilder();
216         for (int i=0; i<DATA.length; ) {
217             cal.clear();
218             cal.set(Calendar.EXTENDED_YEAR, THE_YEAR);
219             buf.setLength(0);
220             buf.append("EXTENDED_YEAR=" + THE_YEAR);
221             while (DATA[i] != END) {
222                 cal.set(DATA[i++], DATA[i++]);
223                 buf.append(" " + fieldName(DATA[i-2]) + "=" + DATA[i-1]);
224             }
225             ++i; // Skip over END mark
226             int expMonth = DATA[i++]-1;
227             int expIsLeapMonth = DATA[i++];
228             int expDOM = DATA[i++];
229             int month = cal.get(Calendar.MONTH);
230             int isLeapMonth = cal.get(Calendar.IS_LEAP_MONTH);
231             int dom = cal.get(Calendar.DAY_OF_MONTH);
232             if (expMonth == month && expIsLeapMonth == isLeapMonth &&
233                 dom == expDOM) {
234                 logln("OK: " + buf + " => " + fmt.format(cal.getTime()));
235             } else {
236                 String s = fmt.format(cal.getTime());
237                 cal.clear();
238                 cal.set(Calendar.EXTENDED_YEAR, THE_YEAR);
239                 cal.set(Calendar.MONTH, expMonth);
240                 cal.set(Calendar.IS_LEAP_MONTH, expIsLeapMonth);
241                 cal.set(Calendar.DAY_OF_MONTH, expDOM);
242                 errln("Fail: " + buf + " => " + s +
243                       "=" + (month+1) + "," + isLeapMonth + "," + dom +
244                       ", expected " + fmt.format(cal.getTime()) +
245                       "=" + (expMonth+1) + "," + expIsLeapMonth + "," + expDOM);
246             }
247         }
248     }
249
250     /**
251      * Test the behavior of fields that are out of range.
252      */
253     public void TestOutOfRange() {
254         int[] DATA = new int[] {
255             // Input       Output
256             4334, 13,  1,   4335,  1,  1,
257             4334, 18,  1,   4335,  6,  1,
258             4335,  0,  1,   4334, 12,  1,
259             4335, -6,  1,   4334,  6,  1,
260             4334,  1, 32,   4334,  2,  2, // 1-4334 has 30 days
261             4334,  2, -1,   4334,  1, 29,
262         };
263         Calendar cal = Calendar.getInstance(new ULocale("ko_KR@calendar=dangi"));
264         for (int i = 0; i < DATA.length;) {
265             int y1 = DATA[i++];
266             int m1 = DATA[i++] - 1;
267             int d1 = DATA[i++];
268             int y2 = DATA[i++];
269             int m2 = DATA[i++] - 1;
270             int d2 = DATA[i++];
271             cal.clear();
272             cal.set(Calendar.EXTENDED_YEAR, y1);
273             cal.set(MONTH, m1);
274             cal.set(DATE, d1);
275             int y = cal.get(Calendar.EXTENDED_YEAR);
276             int m = cal.get(MONTH);
277             int d = cal.get(DATE);
278             if (y != y2 || m != m2 || d != d2) {
279                 errln("Fail: " + y1 + "/" + (m1 + 1) + "/" + d1 + " resolves to " + y + "/" + (m + 1) + "/" + d
280                         + ", expected " + y2 + "/" + (m2 + 1) + "/" + d2);
281             } else if (isVerbose()) {
282                 logln("OK: " + y1 + "/" + (m1 + 1) + "/" + d1 + " resolves to " + y + "/" + (m + 1) + "/" + d);
283             }
284         }
285     }
286
287     /**
288      * Test the behavior of KoreanLunarCalendar.add().  The only real
289      * nastiness with roll is the MONTH field around leap months.
290      */
291     public void TestAdd() {
292         int[][] tests = new int[][] {
293             // MONTHS ARE 1-BASED HERE
294             // input               add           output
295             // year  mon    day    field amount  year  mon    day
296             {  4338,   3,0,  15,   MONTH,   3,   4338,   6,0,  15 }, // normal
297             {  4335,  12,0,  15,   MONTH,   1,   4336,   1,0,  15 }, // across year
298             {  4336,   1,0,  15,   MONTH,  -1,   4335,  12,0,  15 }, // across year
299             {  4334,   3,0,  15,   MONTH,   3,   4334,   5,0,  15 }, // 4=leap
300             {  4334,   3,0,  15,   MONTH,   2,   4334,   4,1,  15 }, // 4=leap
301             {  4334,   4,0,  15,   MONTH,   1,   4334,   4,1,  15 }, // 4=leap
302             {  4334,   4,1,  15,   MONTH,   1,   4334,   5,0,  15 }, // 4=leap
303             {  4334,   3,0,  30,   MONTH,   2,   4334,   4,1,  29 }, // dom should pin
304             {  4334,   3,0,  30,   MONTH,   3,   4334,   5,0,  30 }, // no dom pin
305             {  4334,   3,0,  30,   MONTH,   4,   4334,   6,0,  29 }, // dom should pin
306         };
307        
308         Calendar cal = Calendar.getInstance(new ULocale("ko_KR@calendar=dangi"));
309         doRollAddDangi(ADD, cal, tests);
310     }
311
312     /**
313      * Test the behavior of KoreanLunarCalendar.roll().  The only real
314      * nastiness with roll is the MONTH field around leap months.
315      */
316     public void TestRoll() {
317         int[][] tests = new int[][] {
318             // MONTHS ARE 1-BASED HERE
319             // input               add           output
320             // year  mon    day    field amount  year  mon    day
321             {  4338,   3,0,  15,   MONTH,   3,   4338,   6,0,  15 }, // normal
322             {  4338,   3,0,  15,   MONTH,  11,   4338,   2,0,  15 }, // normal
323             {  4335,  12,0,  15,   MONTH,   1,   4335,   1,0,  15 }, // across year
324             {  4336,   1,0,  15,   MONTH,  -1,   4336,  12,0,  15 }, // across year
325             {  4334,   3,0,  15,   MONTH,   3,   4334,   5,0,  15 }, // 4=leap
326             {  4334,   3,0,  15,   MONTH,  16,   4334,   5,0,  15 }, // 4=leap
327             {  4334,   3,0,  15,   MONTH,   2,   4334,   4,1,  15 }, // 4=leap
328             {  4334,   3,0,  15,   MONTH,  28,   4334,   4,1,  15 }, // 4=leap
329             {  4334,   4,0,  15,   MONTH,   1,   4334,   4,1,  15 }, // 4=leap
330             {  4334,   4,0,  15,   MONTH, -12,   4334,   4,1,  15 }, // 4=leap
331             {  4334,   4,1,  15,   MONTH,   1,   4334,   5,0,  15 }, // 4=leap
332             {  4334,   4,1,  15,   MONTH, -25,   4334,   5,0,  15 }, // 4=leap
333             {  4334,   3,0,  30,   MONTH,   2,   4334,   4,1,  29 }, // dom should pin
334             {  4334,   3,0,  30,   MONTH,  15,   4334,   4,1,  29 }, // dom should pin
335             {  4334,   3,0,  30,   MONTH,  16,   4334,   5,0,  30 }, // no dom pin
336             {  4334,   3,0,  30,   MONTH,  -9,   4334,   6,0,  29 }, // dom should pin
337         };
338        
339         Calendar cal = Calendar.getInstance(new ULocale("ko_KR@calendar=dangi"));
340         doRollAddDangi(ROLL, cal, tests);
341     }
342     
343     void doRollAddDangi(boolean roll, Calendar cal, int[][] tests) {
344         String name = roll ? "rolling" : "adding";
345
346         for (int i = 0; i < tests.length; i++) {
347             int[] test = tests[i];
348
349             cal.clear();
350             cal.set(Calendar.EXTENDED_YEAR, test[0]);
351             cal.set(Calendar.MONTH, test[1] - 1);
352             cal.set(Calendar.IS_LEAP_MONTH, test[2]);
353             cal.set(Calendar.DAY_OF_MONTH, test[3]);
354             if (roll) {
355                 cal.roll(test[4], test[5]);
356             } else {
357                 cal.add(test[4], test[5]);
358             }
359             if (cal.get(Calendar.EXTENDED_YEAR) != test[6] || cal.get(MONTH) != (test[7] - 1)
360                     || cal.get(Calendar.IS_LEAP_MONTH) != test[8] || cal.get(DATE) != test[9]) {
361                 errln("Fail: " + name + " " + ymdToString(test[0], test[1] - 1, test[2], test[3]) + " "
362                         + fieldName(test[4]) + " by " + test[5] + ": expected "
363                         + ymdToString(test[6], test[7] - 1, test[8], test[9]) + ", got " + ymdToString(cal));
364             } else if (isVerbose()) {
365                 logln("OK: " + name + " " + ymdToString(test[0], test[1] - 1, test[2], test[3]) + " "
366                         + fieldName(test[4]) + " by " + test[5] + ": got " + ymdToString(cal));
367             }
368         }
369     }
370
371     /**
372      * Convert year,month,day values to the form "year/month/day".
373      * On input the month value is zero-based, but in the result string it is one-based.
374      */
375     static public String ymdToString(int year, int month, int isLeapMonth, int day) {
376         return "" + year + "/" + (month + 1) + ((isLeapMonth != 0) ? "(leap)" : "") + "/" + day;
377     }
378
379     public void TestCoverage() {
380         // DangiCalendar()
381         // DangiCalendar(Date)
382         // DangiCalendar(TimeZone, ULocale)
383         Date d = new Date();
384
385         DangiCalendar cal1 = new DangiCalendar();
386         cal1.setTime(d);
387
388         DangiCalendar cal2 = new DangiCalendar(d);
389
390         DangiCalendar cal3 = new DangiCalendar(TimeZone.getDefault(), ULocale.getDefault());
391         cal3.setTime(d);
392
393         assertEquals("DangiCalendar() and DangiCalendar(Date)", cal1, cal2);
394         assertEquals("DangiCalendar() and DangiCalendar(TimeZone,ULocale)", cal1, cal3);
395
396         // String getType()
397         String type = cal1.getType();
398         assertEquals("getType()", "dangi", type);
399     }
400
401     public void TestInitWithCurrentTime() {
402         // If the chinese calendar current millis isn't called, the default year is wrong.
403         // this test is assuming the 'year' is the current cycle
404         // so when we cross a cycle boundary, the target will need to change
405         // that shouldn't be for awhile yet... 
406
407         Calendar cc = Calendar.getInstance(new ULocale("ko_KR@calendar=dangi"));
408         cc.set(Calendar.EXTENDED_YEAR, 4338);
409         cc.set(Calendar.MONTH, 0);
410          // need to set leap month flag off, otherwise, the test case always fails when
411          // current time is in a leap month
412         cc.set(Calendar.IS_LEAP_MONTH, 0);
413         cc.set(Calendar.DATE, 19);
414         cc.set(Calendar.HOUR_OF_DAY, 0);
415         cc.set(Calendar.MINUTE, 0);
416         cc.set(Calendar.SECOND, 0);
417         cc.set(Calendar.MILLISECOND, 0);
418
419         cc.add(Calendar.DATE, 1);
420  
421         Calendar cal = new GregorianCalendar(2005, Calendar.FEBRUARY, 28);
422         Date target = cal.getTime();
423         Date result = cc.getTime();
424
425         assertEquals("chinese and gregorian date should match", target, result);
426     }
427 }