001: /*
002: *******************************************************************************
003: * Copyright (C) 1996-2005, International Business Machines Corporation and *
004: * others. All Rights Reserved. *
005: *******************************************************************************
006: */
007:
008: package com.ibm.icu.dev.test.calendar;
009:
010: import java.util.Date;
011: import java.util.Locale;
012: import java.util.MissingResourceException;
013:
014: import com.ibm.icu.impl.LocaleUtility;
015: import com.ibm.icu.text.DateFormat;
016: import com.ibm.icu.util.Calendar;
017: import com.ibm.icu.util.HebrewCalendar;
018: import com.ibm.icu.util.TimeZone;
019: import com.ibm.icu.util.ULocale;
020:
021: /**
022: * Tests for the <code>HebrewCalendar</code> class.
023: */
024: public class HebrewTest extends CalendarTest {
025: public static void main(String args[]) throws Exception {
026: new HebrewTest().run(args);
027: }
028:
029: // Constants to save typing.
030: public static final int TISHRI = HebrewCalendar.TISHRI;
031: public static final int HESHVAN = HebrewCalendar.HESHVAN;
032: public static final int KISLEV = HebrewCalendar.KISLEV;
033: public static final int TEVET = HebrewCalendar.TEVET;
034: public static final int SHEVAT = HebrewCalendar.SHEVAT;
035: public static final int ADAR_1 = HebrewCalendar.ADAR_1;
036: public static final int ADAR = HebrewCalendar.ADAR;
037: public static final int NISAN = HebrewCalendar.NISAN;
038: public static final int IYAR = HebrewCalendar.IYAR;
039: public static final int SIVAN = HebrewCalendar.SIVAN;
040: public static final int TAMUZ = HebrewCalendar.TAMUZ;
041: public static final int AV = HebrewCalendar.AV;
042: public static final int ELUL = HebrewCalendar.ELUL;
043:
044: /**
045: * Test the behavior of HebrewCalendar.roll
046: * The only real nastiness with roll is the MONTH field, since a year can
047: * have a variable number of months.
048: */
049: public void TestRoll() {
050: int[][] tests = new int[][] {
051: // input roll by output
052: // year month day field amount year month day
053:
054: { 5759, HESHVAN, 2, MONTH, 1, 5759, KISLEV, 2 }, // non-leap years
055: { 5759, SHEVAT, 2, MONTH, 1, 5759, ADAR, 2 },
056: { 5759, SHEVAT, 2, MONTH, 2, 5759, NISAN, 2 },
057: { 5759, SHEVAT, 2, MONTH, 12, 5759, SHEVAT, 2 },
058: { 5759, AV, 1, MONTH, 12, 5759, AV, 1 }, // Alan
059:
060: { 5757, HESHVAN, 2, MONTH, 1, 5757, KISLEV, 2 }, // leap years
061: { 5757, SHEVAT, 2, MONTH, 1, 5757, ADAR_1, 2 },
062: { 5757, SHEVAT, 2, MONTH, 2, 5757, ADAR, 2 },
063: { 5757, SHEVAT, 2, MONTH, 3, 5757, NISAN, 2 },
064: { 5757, SHEVAT, 2, MONTH, 12, 5757, TEVET, 2 },
065: { 5757, SHEVAT, 2, MONTH, 13, 5757, SHEVAT, 2 },
066: { 5757, AV, 1, MONTH, 12, 5757, TAMUZ, 1 }, // Alan
067:
068: { 5757, KISLEV, 1, DATE, 30, 5757, KISLEV, 2 }, // 29-day month
069: { 5758, KISLEV, 1, DATE, 31, 5758, KISLEV, 2 }, // 30-day month
070:
071: // Try some other fields too
072: { 5757, TISHRI, 1, YEAR, 1, 5758, TISHRI, 1 },
073:
074: // Try some rolls that require other fields to be adjusted
075: { 5757, TISHRI, 30, MONTH, 1, 5757, HESHVAN, 29 },
076: { 5758, KISLEV, 30, YEAR, -1, 5757, KISLEV, 29 }, };
077: // try{
078: HebrewCalendar cal = new HebrewCalendar(UTC, Locale
079: .getDefault());
080:
081: doRollAdd(ROLL, cal, tests);
082: // }catch(MissingResourceException ex){
083: // warnln("Got Exception: "+ ex.getMessage());
084: // }
085: }
086:
087: /**
088: * Test the behavior of HebrewCalendar.roll
089: * The only real nastiness with roll is the MONTH field, since a year can
090: * have a variable number of months.
091: */
092: public void TestAdd() {
093: int[][] tests = new int[][] {
094: // input add by output
095: // year month day field amount year month day
096: { 5759, HESHVAN, 2, MONTH, 1, 5759, KISLEV, 2 }, // non-leap years
097: { 5759, SHEVAT, 2, MONTH, 1, 5759, ADAR, 2 },
098: { 5759, SHEVAT, 2, MONTH, 2, 5759, NISAN, 2 },
099: { 5759, SHEVAT, 2, MONTH, 12, 5760, SHEVAT, 2 },
100:
101: { 5757, HESHVAN, 2, MONTH, 1, 5757, KISLEV, 2 }, // leap years
102: { 5757, SHEVAT, 2, MONTH, 1, 5757, ADAR_1, 2 },
103: { 5757, SHEVAT, 2, MONTH, 2, 5757, ADAR, 2 },
104: { 5757, SHEVAT, 2, MONTH, 3, 5757, NISAN, 2 },
105: { 5757, SHEVAT, 2, MONTH, 12, 5758, TEVET, 2 },
106: { 5757, SHEVAT, 2, MONTH, 13, 5758, SHEVAT, 2 },
107:
108: { 5762, AV, 1, MONTH, 1, 5762, ELUL, 1 }, // JB#2327
109: { 5762, AV, 30, DATE, 1, 5762, ELUL, 1 }, // JB#2327
110: { 5762, ELUL, 1, DATE, -1, 5762, AV, 30 }, // JB#2327
111: { 5762, ELUL, 1, MONTH, -1, 5762, AV, 1 }, // JB#2327
112:
113: { 5757, KISLEV, 1, DATE, 30, 5757, TEVET, 2 }, // 29-day month
114: { 5758, KISLEV, 1, DATE, 31, 5758, TEVET, 2 }, // 30-day month
115: };
116: try {
117: HebrewCalendar cal = new HebrewCalendar(UTC, Locale
118: .getDefault());
119:
120: doRollAdd(ADD, cal, tests);
121: } catch (MissingResourceException ex) {
122: warnln("Could not load the locale data");
123: }
124: }
125:
126: /**
127: * A huge list of test cases to make sure that computeTime and computeFields
128: * work properly for a wide range of data.
129: */
130: public void TestCases() {
131: try {
132: final TestCase[] testCases = {
133: //
134: // Most of these test cases were taken from the back of
135: // "Calendrical Calculations", with some extras added to help
136: // debug a few of the problems that cropped up in development.
137: //
138: // The months in this table are 1-based rather than 0-based,
139: // because it's easier to edit that way.
140: //
141: // Julian Day Era Year Month Day WkDay Hour Min Sec
142: new TestCase(1507231.5, 0, 3174, 12, 10, SUN, 0, 0,
143: 0),
144: new TestCase(1660037.5, 0, 3593, 3, 25, WED, 0, 0,
145: 0),
146: new TestCase(1746893.5, 0, 3831, 1, 3, WED, 0, 0, 0),
147: new TestCase(1770641.5, 0, 3896, 1, 9, SUN, 0, 0, 0),
148: new TestCase(1892731.5, 0, 4230, 4, 18, WED, 0, 0,
149: 0),
150: new TestCase(1931579.5, 0, 4336, 10, 4, MON, 0, 0,
151: 0),
152: new TestCase(1974851.5, 0, 4455, 2, 13, SAT, 0, 0,
153: 0),
154: new TestCase(2091164.5, 0, 4773, 9, 6, SUN, 0, 0, 0),
155: new TestCase(2121509.5, 0, 4856, 9, 23, SUN, 0, 0,
156: 0),
157: new TestCase(2155779.5, 0, 4950, 8, 7, FRI, 0, 0, 0),
158: new TestCase(2174029.5, 0, 5000, 7, 8, SAT, 0, 0, 0),
159: new TestCase(2191584.5, 0, 5048, 8, 21, FRI, 0, 0,
160: 0),
161: new TestCase(2195261.5, 0, 5058, 9, 7, SUN, 0, 0, 0),
162: new TestCase(2229274.5, 0, 5151, 11, 1, SUN, 0, 0,
163: 0),
164: new TestCase(2245580.5, 0, 5196, 5, 7, WED, 0, 0, 0),
165: new TestCase(2266100.5, 0, 5252, 8, 3, SAT, 0, 0, 0),
166: new TestCase(2288542.5, 0, 5314, 1, 1, SAT, 0, 0, 0),
167: new TestCase(2290901.5, 0, 5320, 6, 27, SAT, 0, 0,
168: 0),
169: new TestCase(2323140.5, 0, 5408, 10, 20, WED, 0, 0,
170: 0),
171: new TestCase(2334551.5, 0, 5440, 1, 1, THU, 0, 0, 0),
172: new TestCase(2334581.5, 0, 5440, 2, 1, SAT, 0, 0, 0),
173: new TestCase(2334610.5, 0, 5440, 3, 1, SUN, 0, 0, 0),
174: new TestCase(2334639.5, 0, 5440, 4, 1, MON, 0, 0, 0),
175: new TestCase(2334668.5, 0, 5440, 5, 1, TUE, 0, 0, 0),
176: new TestCase(2334698.5, 0, 5440, 6, 1, THU, 0, 0, 0),
177: new TestCase(2334728.5, 0, 5440, 7, 1, SAT, 0, 0, 0),
178: new TestCase(2334757.5, 0, 5440, 8, 1, SUN, 0, 0, 0),
179: new TestCase(2334787.5, 0, 5440, 9, 1, TUE, 0, 0, 0),
180: new TestCase(2334816.5, 0, 5440, 10, 1, WED, 0, 0,
181: 0),
182: new TestCase(2334846.5, 0, 5440, 11, 1, FRI, 0, 0,
183: 0),
184: new TestCase(2334848.5, 0, 5440, 11, 3, SUN, 0, 0,
185: 0),
186: new TestCase(2334934.5, 0, 5441, 1, 1, TUE, 0, 0, 0),
187: new TestCase(2348020.5, 0, 5476, 12, 5, FRI, 0, 0,
188: 0),
189: new TestCase(2366978.5, 0, 5528, 11, 4, SUN, 0, 0,
190: 0),
191: new TestCase(2385648.5, 0, 5579, 12, 11, MON, 0, 0,
192: 0),
193: new TestCase(2392825.5, 0, 5599, 8, 12, WED, 0, 0,
194: 0),
195: new TestCase(2416223.5, 0, 5663, 8, 22, SUN, 0, 0,
196: 0),
197: new TestCase(2425848.5, 0, 5689, 12, 19, SUN, 0, 0,
198: 0),
199: new TestCase(2430266.5, 0, 5702, 1, 8, MON, 0, 0, 0),
200: new TestCase(2430833.5, 0, 5703, 8, 14, MON, 0, 0,
201: 0),
202: new TestCase(2431004.5, 0, 5704, 1, 8, THU, 0, 0, 0),
203: new TestCase(2448698.5, 0, 5752, 7, 12, TUE, 0, 0,
204: 0),
205: new TestCase(2450138.5, 0, 5756, 7, 5, SUN, 0, 0, 0),
206: new TestCase(2465737.5, 0, 5799, 2, 12, WED, 0, 0,
207: 0),
208: new TestCase(2486076.5, 0, 5854, 12, 5, SUN, 0, 0,
209: 0),
210:
211: // Additional test cases for bugs found during development
212: // G.YY/MM/DD Era Year Month Day WkDay Hour Min Sec
213: new TestCase(1013, 9, 8, 0, 4774, 1, 1, TUE, 0, 0,
214: 0),
215: new TestCase(1239, 9, 1, 0, 5000, 1, 1, THU, 0, 0,
216: 0),
217: new TestCase(1240, 9, 18, 0, 5001, 1, 1, TUE, 0, 0,
218: 0),
219:
220: // Test cases taken from a table of 14 "year types" in the Help file
221: // of the application "Hebrew Calendar"
222: new TestCase(2456187.5, 0, 5773, 1, 1, MON, 0, 0, 0),
223: new TestCase(2459111.5, 0, 5781, 1, 1, SAT, 0, 0, 0),
224: new TestCase(2453647.5, 0, 5766, 1, 1, TUE, 0, 0, 0),
225: new TestCase(2462035.5, 0, 5789, 1, 1, THU, 0, 0, 0),
226: new TestCase(2458756.5, 0, 5780, 1, 1, MON, 0, 0, 0),
227: new TestCase(2460586.5, 0, 5785, 1, 1, THU, 0, 0, 0),
228: new TestCase(2463864.5, 0, 5794, 1, 1, SAT, 0, 0, 0),
229: new TestCase(2463481.5, 0, 5793, 1, 1, MON, 0, 0, 0),
230: new TestCase(2470421.5, 0, 5812, 1, 1, THU, 0, 0, 0),
231: new TestCase(2460203.5, 0, 5784, 1, 1, SAT, 0, 0, 0),
232: new TestCase(2459464.5, 0, 5782, 1, 1, TUE, 0, 0, 0),
233: new TestCase(2467142.5, 0, 5803, 1, 1, MON, 0, 0, 0),
234: new TestCase(2455448.5, 0, 5771, 1, 1, THU, 0, 0, 0),
235:
236: // Test cases for JB#2327
237: // http://www.fourmilab.com/documents/calendar/
238: // http://www.calendarhome.com/converter/
239: // 2452465.5, 2002, JULY, 10, 5762, AV, 1,
240: // 2452494.5, 2002, AUGUST, 8, 5762, AV, 30,
241: // 2452495.5, 2002, AUGUST, 9, 5762, ELUL, 1,
242: // 2452523.5, 2002, SEPTEMBER, 6, 5762, ELUL, 29,
243: // 2452524.5, 2002, SEPTEMBER, 7, 5763, TISHRI, 1,
244: // Julian Day Era Year Month Day WkDay Hour Min Sec
245: new TestCase(2452465.5, 0, 5762, AV + 1, 1, WED, 0,
246: 0, 0),
247: new TestCase(2452494.5, 0, 5762, AV + 1, 30, THU,
248: 0, 0, 0),
249: new TestCase(2452495.5, 0, 5762, ELUL + 1, 1, FRI,
250: 0, 0, 0),
251: new TestCase(2452523.5, 0, 5762, ELUL + 1, 29, FRI,
252: 0, 0, 0),
253: new TestCase(2452524.5, 0, 5763, TISHRI + 1, 1,
254: SAT, 0, 0, 0), };
255: doTestCases(testCases, new HebrewCalendar());
256:
257: } catch (MissingResourceException ex) {
258: warnln("Got Exception: " + ex.getMessage());
259: }
260: }
261:
262: /**
263: * Problem reported by Armand Bendanan in which setting of the MONTH
264: * field in a Hebrew calendar causes the time fields to go negative.
265: */
266: public void TestTimeFields() {
267: try {
268: HebrewCalendar calendar = new HebrewCalendar(5761, 0, 11,
269: 12, 28, 15);
270: calendar.set(Calendar.YEAR, 5717);
271: calendar.set(Calendar.MONTH, 2);
272: calendar.set(Calendar.DAY_OF_MONTH, 23);
273: if (calendar.get(Calendar.HOUR_OF_DAY) != 12) {
274: errln("Fail: HebrewCalendar HOUR_OF_DAY = "
275: + calendar.get(Calendar.HOUR_OF_DAY));
276: }
277: } catch (MissingResourceException ex) {
278: warnln("Got Exception: " + ex.getMessage());
279: }
280: }
281:
282: /**
283: * Problem reported by Armand Bendanan (armand.bendanan@free.fr)
284: * in which setting of the MONTH field in a Hebrew calendar to
285: * ELUL on non leap years causes the date to be set on TISHRI next year.
286: */
287: public void TestElulMonth() {
288: try {
289: HebrewCalendar cal = new HebrewCalendar();
290: // Leap years are:
291: // 3 6 8 11 14 17 19 (and so on - 19-year cycle)
292: for (int year = 1; year < 50; year++) {
293: // I hope that year = 0 does not exists
294: // because the test fails for it !
295: cal.clear();
296:
297: cal.set(Calendar.YEAR, year);
298: cal.set(Calendar.MONTH, ELUL);
299: cal.set(Calendar.DAY_OF_MONTH, 1);
300:
301: int yact = cal.get(Calendar.YEAR);
302: int mact = cal.get(Calendar.MONTH);
303:
304: if (year != yact || ELUL != mact) {
305: errln("Fail: " + ELUL + "/" + year + " -> " + mact
306: + "/" + yact);
307: }
308: }
309: } catch (MissingResourceException ex) {
310: warnln("Got Exception: " + ex.getMessage());
311: }
312: }
313:
314: /**
315: * Test of the behavior of the month field. This requires special
316: * handling in the Hebrew calendar because of the pattern of leap
317: * years.
318: */
319: public void TestMonthMovement() {
320: try {
321: HebrewCalendar cal = new HebrewCalendar();
322: // Leap years are:
323: // 3 6 8 11 14 17 19 (and so on - 19-year cycle)
324: // We can't test complete() on some lines below because of ADAR_1 -- if
325: // the calendar is set to ADAR_1 on a non-leap year, the result is undefined.
326: int[] DATA = {
327: // m1/y1 - month/year before (month is 1-based)
328: // delta - amount to add to month field
329: // m2/y2 - month/year after add(MONTH, delta)
330: // m3/y3 - month/year after set(MONTH, m1+delta)
331: //m1 y1 delta m2 y2 m3 y3
332: 10, 2, +24, 9, 4, 9, 4, 10, 2, +60, 8, 7, 8, 7, 1,
333: 2, +12, 1, 3, 13,
334: 2, //*set != add; also see '*' below
335: 3, 18, -24, 4, 16, 4, 16, 1, 6, -24, 1, 4, 1, 4, 4,
336: 3, +2, 6, 3, 6, 3, // Leap year - no skip 4,5,6,7,8
337: 8, 3, -2, 6, 3, 6, 3, // Leap year - no skip
338: 4, 2, +2, 7, 2, 7, 2, // Skip leap month 4,5,(6),7,8
339: 8, 2, -2, 5, 2, 7, 2, //*Skip leap month going backward
340: };
341: for (int i = 0; i < DATA.length;) {
342: int m = DATA[i++], y = DATA[i++];
343: int monthDelta = DATA[i++];
344: int m2 = DATA[i++], y2 = DATA[i++];
345: int m3 = DATA[i++], y3 = DATA[i++];
346: int mact, yact;
347:
348: cal.clear();
349: cal.set(Calendar.YEAR, y);
350: cal.set(Calendar.MONTH, m - 1);
351: cal.add(Calendar.MONTH, monthDelta);
352: yact = cal.get(Calendar.YEAR);
353: mact = cal.get(Calendar.MONTH) + 1;
354: if (y2 != yact || m2 != mact) {
355: errln("Fail: " + m + "/" + y + " -> add(MONTH, "
356: + monthDelta + ") -> " + mact + "/" + yact
357: + ", expected " + m2 + "/" + y2);
358: cal.clear();
359: cal.set(Calendar.YEAR, y);
360: cal.set(Calendar.MONTH, m - 1);
361: logln("Start: " + m + "/" + y);
362: int delta = monthDelta > 0 ? 1 : -1;
363: for (int c = 0; c != monthDelta; c += delta) {
364: cal.add(Calendar.MONTH, delta);
365: logln("+ " + delta + " MONTH -> "
366: + (cal.get(Calendar.MONTH) + 1) + "/"
367: + cal.get(Calendar.YEAR));
368: }
369: }
370:
371: cal.clear();
372: cal.set(Calendar.YEAR, y);
373: cal.set(Calendar.MONTH, m + monthDelta - 1);
374: yact = cal.get(Calendar.YEAR);
375: mact = cal.get(Calendar.MONTH) + 1;
376: if (y3 != yact || m3 != mact) {
377: errln("Fail: " + (m + monthDelta) + "/" + y
378: + " -> complete() -> " + mact + "/" + yact
379: + ", expected " + m3 + "/" + y3);
380: }
381: }
382: } catch (MissingResourceException ex) {
383: warnln("Got Exception: " + ex.getMessage());
384: }
385: }
386:
387: /**
388: * Test handling of ADAR_1.
389: */
390: /*
391: public void TestAdar1() {
392: HebrewCalendar cal = new HebrewCalendar();
393: cal.clear();
394: cal.set(Calendar.YEAR, 1903); // leap
395: cal.set(Calendar.MONTH, HebrewCalendar.ADAR_1);
396: logln("1903(leap)/ADAR_1 => " +
397: cal.get(Calendar.YEAR) + "/" + (cal.get(Calendar.MONTH)+1));
398:
399: cal.clear();
400: cal.set(Calendar.YEAR, 1904); // non-leap
401: cal.set(Calendar.MONTH, HebrewCalendar.ADAR_1);
402: logln("1904(non-leap)/ADAR_1 => " +
403: cal.get(Calendar.YEAR) + "/" + (cal.get(Calendar.MONTH)+1));
404: }
405: */
406:
407: /**
408: * With no fields set, the calendar should use default values.
409: */
410: public void TestDefaultFieldValues() {
411: try {
412: HebrewCalendar cal = new HebrewCalendar();
413: cal.clear();
414: logln("cal.clear() -> " + cal.getTime());
415: } catch (MissingResourceException ex) {
416: warnln("could not load the locale data");
417: }
418: }
419:
420: public void TestCoverage() {
421: try {
422: {
423: // new HebrewCalendar(TimeZone)
424: HebrewCalendar cal = new HebrewCalendar(TimeZone
425: .getDefault());
426: if (cal == null) {
427: errln("could not create HebrewCalendar with TimeZone");
428: }
429: }
430:
431: {
432: // new HebrewCalendar(ULocale)
433: HebrewCalendar cal = new HebrewCalendar(ULocale
434: .getDefault());
435: if (cal == null) {
436: errln("could not create HebrewCalendar with ULocale");
437: }
438: }
439:
440: {
441: // new HebrewCalendar(Locale)
442: HebrewCalendar cal = new HebrewCalendar(Locale
443: .getDefault());
444: if (cal == null) {
445: errln("could not create HebrewCalendar with locale");
446: }
447: }
448:
449: {
450: // new HebrewCalendar(Date)
451: HebrewCalendar cal = new HebrewCalendar(new Date());
452: if (cal == null) {
453: errln("could not create HebrewCalendar with date");
454: }
455: }
456:
457: {
458: // data
459: HebrewCalendar cal = new HebrewCalendar(2800,
460: HebrewCalendar.SHEVAT, 1);
461: Date time = cal.getTime();
462:
463: String[] calendarLocales = { "iw_IL" };
464:
465: String[] formatLocales = { "en", "fi", "fr", "hu",
466: "iw", "nl" };
467: for (int i = 0; i < calendarLocales.length; ++i) {
468: String calLocName = calendarLocales[i];
469: Locale calLocale = LocaleUtility
470: .getLocaleFromName(calLocName);
471: cal = new HebrewCalendar(calLocale);
472:
473: for (int j = 0; j < formatLocales.length; ++j) {
474: String locName = formatLocales[j];
475: Locale formatLocale = LocaleUtility
476: .getLocaleFromName(locName);
477: DateFormat format = DateFormat
478: .getDateTimeInstance(cal,
479: DateFormat.FULL,
480: DateFormat.FULL, formatLocale);
481: logln(calLocName + "/" + locName + " --> "
482: + format.format(time));
483: }
484: }
485: }
486: } catch (MissingResourceException ex) {
487: warnln("Could not load the locale data. " + ex.getMessage());
488: }
489: }
490: }
|