2 *******************************************************************************
3 * Copyright (C) 1996-2009, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 *******************************************************************************
8 package com.ibm.icu.dev.test.calendar;
10 import java.util.Locale;
11 import java.util.MissingResourceException;
13 import com.ibm.icu.impl.LocaleUtility;
14 import com.ibm.icu.text.DateFormat;
15 import com.ibm.icu.util.Calendar;
16 import com.ibm.icu.util.HebrewCalendar;
17 import com.ibm.icu.util.TimeZone;
18 import com.ibm.icu.util.ULocale;
21 * Tests for the <code>HebrewCalendar</code> class.
23 public class HebrewTest extends CalendarTest {
24 public static void main(String args[]) throws Exception {
25 new HebrewTest().run(args);
28 // Constants to save typing.
29 public static final int TISHRI = HebrewCalendar.TISHRI;
30 public static final int HESHVAN = HebrewCalendar.HESHVAN;
31 public static final int KISLEV = HebrewCalendar.KISLEV;
32 public static final int TEVET = HebrewCalendar.TEVET;
33 public static final int SHEVAT = HebrewCalendar.SHEVAT;
34 public static final int ADAR_1 = HebrewCalendar.ADAR_1;
35 public static final int ADAR = HebrewCalendar.ADAR;
36 public static final int NISAN = HebrewCalendar.NISAN;
37 public static final int IYAR = HebrewCalendar.IYAR;
38 public static final int SIVAN = HebrewCalendar.SIVAN;
39 public static final int TAMUZ = HebrewCalendar.TAMUZ;
40 public static final int AV = HebrewCalendar.AV;
41 public static final int ELUL = HebrewCalendar.ELUL;
44 * Test the behavior of HebrewCalendar.roll
45 * The only real nastiness with roll is the MONTH field, since a year can
46 * have a variable number of months.
48 public void TestRoll() {
49 int[][] tests = new int[][] {
50 // input roll by output
51 // year month day field amount year month day
53 { 5759, HESHVAN, 2, MONTH, 1, 5759, KISLEV, 2 }, // non-leap years
54 { 5759, SHEVAT, 2, MONTH, 1, 5759, ADAR, 2 },
55 { 5759, SHEVAT, 2, MONTH, 2, 5759, NISAN, 2 },
56 { 5759, SHEVAT, 2, MONTH, 12, 5759, SHEVAT, 2 },
57 { 5759, AV, 1, MONTH, 12, 5759, AV, 1 }, // Alan
59 { 5757, HESHVAN, 2, MONTH, 1, 5757, KISLEV, 2 }, // leap years
60 { 5757, SHEVAT, 2, MONTH, 1, 5757, ADAR_1, 2 },
61 { 5757, SHEVAT, 2, MONTH, 2, 5757, ADAR, 2 },
62 { 5757, SHEVAT, 2, MONTH, 3, 5757, NISAN, 2 },
63 { 5757, SHEVAT, 2, MONTH, 12, 5757, TEVET, 2 },
64 { 5757, SHEVAT, 2, MONTH, 13, 5757, SHEVAT, 2 },
65 { 5757, AV, 1, MONTH, 12, 5757, TAMUZ, 1 }, // Alan
67 { 5757, KISLEV, 1, DATE, 30, 5757, KISLEV, 2 }, // 29-day month
68 { 5758, KISLEV, 1, DATE, 31, 5758, KISLEV, 2 }, // 30-day month
70 // Try some other fields too
71 { 5757, TISHRI, 1, YEAR, 1, 5758, TISHRI, 1 },
74 // Try some rolls that require other fields to be adjusted
75 { 5757, TISHRI, 30, MONTH, 1, 5757, HESHVAN, 29 },
76 { 5758, KISLEV, 30, YEAR, -1, 5757, KISLEV, 29 },
79 HebrewCalendar cal = new HebrewCalendar(UTC, Locale.getDefault());
81 doRollAdd(ROLL, cal, tests);
82 // }catch(MissingResourceException ex){
83 // warnln("Got Exception: "+ ex.getMessage());
88 * Test the behavior of HebrewCalendar.roll
89 * The only real nastiness with roll is the MONTH field, since a year can
90 * have a variable number of months.
92 public void TestAdd() {
93 int[][] tests = new int[][] {
94 // input add by output
95 // year month day field amount year month day
96 { 5759, HESHVAN, 2, MONTH, 1, 5759, KISLEV, 2 }, // non-leap years
97 { 5759, SHEVAT, 2, MONTH, 1, 5759, ADAR, 2 },
98 { 5759, SHEVAT, 2, MONTH, 2, 5759, NISAN, 2 },
99 { 5759, SHEVAT, 2, MONTH, 12, 5760, SHEVAT, 2 },
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 },
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
113 { 5757, KISLEV, 1, DATE, 30, 5757, TEVET, 2 }, // 29-day month
114 { 5758, KISLEV, 1, DATE, 31, 5758, TEVET, 2 }, // 30-day month
117 HebrewCalendar cal = new HebrewCalendar(UTC, Locale.getDefault());
119 doRollAdd(ADD, cal, tests);
120 }catch( MissingResourceException ex){
121 warnln("Could not load the locale data");
126 * A huge list of test cases to make sure that computeTime and computeFields
127 * work properly for a wide range of data.
129 public void TestCases() {
131 final TestCase[] testCases = {
133 // Most of these test cases were taken from the back of
134 // "Calendrical Calculations", with some extras added to help
135 // debug a few of the problems that cropped up in development.
137 // The months in this table are 1-based rather than 0-based,
138 // because it's easier to edit that way.
140 // Julian Day Era Year Month Day WkDay Hour Min Sec
141 new TestCase(1507231.5, 0, 3174, 12, 10, SUN, 0, 0, 0),
142 new TestCase(1660037.5, 0, 3593, 3, 25, WED, 0, 0, 0),
143 new TestCase(1746893.5, 0, 3831, 1, 3, WED, 0, 0, 0),
144 new TestCase(1770641.5, 0, 3896, 1, 9, SUN, 0, 0, 0),
145 new TestCase(1892731.5, 0, 4230, 4, 18, WED, 0, 0, 0),
146 new TestCase(1931579.5, 0, 4336, 10, 4, MON, 0, 0, 0),
147 new TestCase(1974851.5, 0, 4455, 2, 13, SAT, 0, 0, 0),
148 new TestCase(2091164.5, 0, 4773, 9, 6, SUN, 0, 0, 0),
149 new TestCase(2121509.5, 0, 4856, 9, 23, SUN, 0, 0, 0),
150 new TestCase(2155779.5, 0, 4950, 8, 7, FRI, 0, 0, 0),
151 new TestCase(2174029.5, 0, 5000, 7, 8, SAT, 0, 0, 0),
152 new TestCase(2191584.5, 0, 5048, 8, 21, FRI, 0, 0, 0),
153 new TestCase(2195261.5, 0, 5058, 9, 7, SUN, 0, 0, 0),
154 new TestCase(2229274.5, 0, 5151, 11, 1, SUN, 0, 0, 0),
155 new TestCase(2245580.5, 0, 5196, 5, 7, WED, 0, 0, 0),
156 new TestCase(2266100.5, 0, 5252, 8, 3, SAT, 0, 0, 0),
157 new TestCase(2288542.5, 0, 5314, 1, 1, SAT, 0, 0, 0),
158 new TestCase(2290901.5, 0, 5320, 6, 27, SAT, 0, 0, 0),
159 new TestCase(2323140.5, 0, 5408, 10, 20, WED, 0, 0, 0),
160 new TestCase(2334551.5, 0, 5440, 1, 1, THU, 0, 0, 0),
161 new TestCase(2334581.5, 0, 5440, 2, 1, SAT, 0, 0, 0),
162 new TestCase(2334610.5, 0, 5440, 3, 1, SUN, 0, 0, 0),
163 new TestCase(2334639.5, 0, 5440, 4, 1, MON, 0, 0, 0),
164 new TestCase(2334668.5, 0, 5440, 5, 1, TUE, 0, 0, 0),
165 new TestCase(2334698.5, 0, 5440, 6, 1, THU, 0, 0, 0),
166 new TestCase(2334728.5, 0, 5440, 7, 1, SAT, 0, 0, 0),
167 new TestCase(2334757.5, 0, 5440, 8, 1, SUN, 0, 0, 0),
168 new TestCase(2334787.5, 0, 5440, 9, 1, TUE, 0, 0, 0),
169 new TestCase(2334816.5, 0, 5440, 10, 1, WED, 0, 0, 0),
170 new TestCase(2334846.5, 0, 5440, 11, 1, FRI, 0, 0, 0),
171 new TestCase(2334848.5, 0, 5440, 11, 3, SUN, 0, 0, 0),
172 new TestCase(2334934.5, 0, 5441, 1, 1, TUE, 0, 0, 0),
173 new TestCase(2348020.5, 0, 5476, 12, 5, FRI, 0, 0, 0),
174 new TestCase(2366978.5, 0, 5528, 11, 4, SUN, 0, 0, 0),
175 new TestCase(2385648.5, 0, 5579, 12, 11, MON, 0, 0, 0),
176 new TestCase(2392825.5, 0, 5599, 8, 12, WED, 0, 0, 0),
177 new TestCase(2416223.5, 0, 5663, 8, 22, SUN, 0, 0, 0),
178 new TestCase(2425848.5, 0, 5689, 12, 19, SUN, 0, 0, 0),
179 new TestCase(2430266.5, 0, 5702, 1, 8, MON, 0, 0, 0),
180 new TestCase(2430833.5, 0, 5703, 8, 14, MON, 0, 0, 0),
181 new TestCase(2431004.5, 0, 5704, 1, 8, THU, 0, 0, 0),
182 new TestCase(2448698.5, 0, 5752, 7, 12, TUE, 0, 0, 0),
183 new TestCase(2450138.5, 0, 5756, 7, 5, SUN, 0, 0, 0),
184 new TestCase(2465737.5, 0, 5799, 2, 12, WED, 0, 0, 0),
185 new TestCase(2486076.5, 0, 5854, 12, 5, SUN, 0, 0, 0),
187 // Additional test cases for bugs found during development
188 // G.YY/MM/DD Era Year Month Day WkDay Hour Min Sec
189 new TestCase(1013, 9, 8, 0, 4774, 1, 1, TUE, 0, 0, 0),
190 new TestCase(1239, 9, 1, 0, 5000, 1, 1, THU, 0, 0, 0),
191 new TestCase(1240, 9,18, 0, 5001, 1, 1, TUE, 0, 0, 0),
193 // Test cases taken from a table of 14 "year types" in the Help file
194 // of the application "Hebrew Calendar"
195 new TestCase(2456187.5, 0, 5773, 1, 1, MON, 0, 0, 0),
196 new TestCase(2459111.5, 0, 5781, 1, 1, SAT, 0, 0, 0),
197 new TestCase(2453647.5, 0, 5766, 1, 1, TUE, 0, 0, 0),
198 new TestCase(2462035.5, 0, 5789, 1, 1, THU, 0, 0, 0),
199 new TestCase(2458756.5, 0, 5780, 1, 1, MON, 0, 0, 0),
200 new TestCase(2460586.5, 0, 5785, 1, 1, THU, 0, 0, 0),
201 new TestCase(2463864.5, 0, 5794, 1, 1, SAT, 0, 0, 0),
202 new TestCase(2463481.5, 0, 5793, 1, 1, MON, 0, 0, 0),
203 new TestCase(2470421.5, 0, 5812, 1, 1, THU, 0, 0, 0),
204 new TestCase(2460203.5, 0, 5784, 1, 1, SAT, 0, 0, 0),
205 new TestCase(2459464.5, 0, 5782, 1, 1, TUE, 0, 0, 0),
206 new TestCase(2467142.5, 0, 5803, 1, 1, MON, 0, 0, 0),
207 new TestCase(2455448.5, 0, 5771, 1, 1, THU, 0, 0, 0),
209 // Test cases for JB#2327
210 // http://www.fourmilab.com/documents/calendar/
211 // http://www.calendarhome.com/converter/
212 // 2452465.5, 2002, JULY, 10, 5762, AV, 1,
213 // 2452494.5, 2002, AUGUST, 8, 5762, AV, 30,
214 // 2452495.5, 2002, AUGUST, 9, 5762, ELUL, 1,
215 // 2452523.5, 2002, SEPTEMBER, 6, 5762, ELUL, 29,
216 // 2452524.5, 2002, SEPTEMBER, 7, 5763, TISHRI, 1,
217 // Julian Day Era Year Month Day WkDay Hour Min Sec
218 new TestCase(2452465.5, 0, 5762, AV+1, 1, WED, 0, 0, 0),
219 new TestCase(2452494.5, 0, 5762, AV+1, 30, THU, 0, 0, 0),
220 new TestCase(2452495.5, 0, 5762, ELUL+1, 1, FRI, 0, 0, 0),
221 new TestCase(2452523.5, 0, 5762, ELUL+1, 29, FRI, 0, 0, 0),
222 new TestCase(2452524.5, 0, 5763,TISHRI+1, 1, SAT, 0, 0, 0),
224 doTestCases(testCases, new HebrewCalendar());
226 }catch(MissingResourceException ex){
227 warnln("Got Exception: "+ ex.getMessage());
232 * Problem reported by Armand Bendanan in which setting of the MONTH
233 * field in a Hebrew calendar causes the time fields to go negative.
235 public void TestTimeFields() {
237 HebrewCalendar calendar = new HebrewCalendar(5761, 0, 11, 12, 28, 15);
238 calendar.set(Calendar.YEAR, 5717);
239 calendar.set(Calendar.MONTH, 2);
240 calendar.set(Calendar.DAY_OF_MONTH, 23);
241 if (calendar.get(Calendar.HOUR_OF_DAY) != 12) {
242 errln("Fail: HebrewCalendar HOUR_OF_DAY = " + calendar.get(Calendar.HOUR_OF_DAY));
244 }catch(MissingResourceException ex){
245 warnln("Got Exception: "+ ex.getMessage());
250 * Problem reported by Armand Bendanan (armand.bendanan@free.fr)
251 * in which setting of the MONTH field in a Hebrew calendar to
252 * ELUL on non leap years causes the date to be set on TISHRI next year.
254 public void TestElulMonth() {
256 HebrewCalendar cal = new HebrewCalendar();
258 // 3 6 8 11 14 17 19 (and so on - 19-year cycle)
259 for (int year=1; year<50; year++) {
260 // I hope that year = 0 does not exists
261 // because the test fails for it !
264 cal.set(Calendar.YEAR, year);
265 cal.set(Calendar.MONTH, ELUL);
266 cal.set(Calendar.DAY_OF_MONTH, 1);
268 int yact = cal.get(Calendar.YEAR);
269 int mact = cal.get(Calendar.MONTH);
271 if (year != yact || ELUL != mact) {
272 errln("Fail: " + ELUL + "/" + year +
277 }catch(MissingResourceException ex){
278 warnln("Got Exception: "+ ex.getMessage());
283 * Test of the behavior of the month field. This requires special
284 * handling in the Hebrew calendar because of the pattern of leap
287 public void TestMonthMovement() {
289 HebrewCalendar cal = new HebrewCalendar();
291 // 3 6 8 11 14 17 19 (and so on - 19-year cycle)
292 // We can't test complete() on some lines below because of ADAR_1 -- if
293 // the calendar is set to ADAR_1 on a non-leap year, the result is undefined.
295 // m1/y1 - month/year before (month is 1-based)
296 // delta - amount to add to month field
297 // m2/y2 - month/year after add(MONTH, delta)
298 // m3/y3 - month/year after set(MONTH, m1+delta)
299 //m1 y1 delta m2 y2 m3 y3
300 10, 2, +24, 9, 4, 9, 4,
301 10, 2, +60, 8, 7, 8, 7,
302 1 , 2, +12, 1, 3, 13, 2, //*set != add; also see '*' below
303 3 , 18, -24, 4, 16, 4, 16,
304 1 , 6, -24, 1, 4, 1, 4,
305 4 , 3, +2, 6, 3, 6, 3, // Leap year - no skip 4,5,6,7,8
306 8 , 3, -2, 6, 3, 6, 3, // Leap year - no skip
307 4 , 2, +2, 7, 2, 7, 2, // Skip leap month 4,5,(6),7,8
308 8 , 2, -2, 5, 2, 7, 2, //*Skip leap month going backward
310 for (int i=0; i<DATA.length; ) {
311 int m = DATA[i++], y = DATA[i++];
312 int monthDelta = DATA[i++];
313 int m2 = DATA[i++], y2 = DATA[i++];
314 int m3 = DATA[i++], y3 = DATA[i++];
318 cal.set(Calendar.YEAR, y);
319 cal.set(Calendar.MONTH, m-1);
320 cal.add(Calendar.MONTH, monthDelta);
321 yact = cal.get(Calendar.YEAR); mact = cal.get(Calendar.MONTH) + 1;
322 if (y2 != yact || m2 != mact) {
323 errln("Fail: " + m + "/" + y +
324 " -> add(MONTH, " + monthDelta + ") -> " +
325 mact + "/" + yact + ", expected " +
328 cal.set(Calendar.YEAR, y);
329 cal.set(Calendar.MONTH, m-1);
330 logln("Start: " + m + "/" + y);
331 int delta = monthDelta > 0 ? 1 : -1;
332 for (int c=0; c!=monthDelta; c+=delta) {
333 cal.add(Calendar.MONTH, delta);
334 logln("+ " + delta + " MONTH -> " +
335 (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.YEAR));
340 cal.set(Calendar.YEAR, y);
341 cal.set(Calendar.MONTH, m + monthDelta - 1);
342 yact = cal.get(Calendar.YEAR); mact = cal.get(Calendar.MONTH) + 1;
343 if (y3 != yact || m3 != mact) {
344 errln("Fail: " + (m+monthDelta) + "/" + y +
345 " -> complete() -> " +
346 mact + "/" + yact + ", expected " +
350 }catch(MissingResourceException ex){
351 warnln("Got Exception: "+ ex.getMessage());
356 * Test handling of ADAR_1.
359 public void TestAdar1() {
360 HebrewCalendar cal = new HebrewCalendar();
362 cal.set(Calendar.YEAR, 1903); // leap
363 cal.set(Calendar.MONTH, HebrewCalendar.ADAR_1);
364 logln("1903(leap)/ADAR_1 => " +
365 cal.get(Calendar.YEAR) + "/" + (cal.get(Calendar.MONTH)+1));
368 cal.set(Calendar.YEAR, 1904); // non-leap
369 cal.set(Calendar.MONTH, HebrewCalendar.ADAR_1);
370 logln("1904(non-leap)/ADAR_1 => " +
371 cal.get(Calendar.YEAR) + "/" + (cal.get(Calendar.MONTH)+1));
376 * With no fields set, the calendar should use default values.
378 public void TestDefaultFieldValues() {
380 HebrewCalendar cal = new HebrewCalendar();
382 logln("cal.clear() -> " + cal.getTime());
383 }catch(MissingResourceException ex){
384 warnln("could not load the locale data");
389 * Test limits of the Hebrew calendar
391 public void TestLimits() {
392 Calendar cal = Calendar.getInstance();
393 cal.set(2007, Calendar.JANUARY, 1);
394 HebrewCalendar hebrew = new HebrewCalendar();
395 doLimitsTest(hebrew, null, cal.getTime());
396 doTheoreticalLimitsTest(hebrew, true);
399 public void TestCoverage() {
402 // new HebrewCalendar(TimeZone)
403 HebrewCalendar cal = new HebrewCalendar(TimeZone.getDefault());
405 errln("could not create HebrewCalendar with TimeZone");
410 // new HebrewCalendar(ULocale)
411 HebrewCalendar cal = new HebrewCalendar(ULocale.getDefault());
413 errln("could not create HebrewCalendar with ULocale");
418 // new HebrewCalendar(Locale)
419 HebrewCalendar cal = new HebrewCalendar(Locale.getDefault());
421 errln("could not create HebrewCalendar with locale");
426 // new HebrewCalendar(Date)
427 HebrewCalendar cal = new HebrewCalendar(new Date());
429 errln("could not create HebrewCalendar with date");
435 HebrewCalendar cal = new HebrewCalendar(2800, HebrewCalendar.SHEVAT, 1);
436 Date time = cal.getTime();
438 String[] calendarLocales = {
442 String[] formatLocales = {
443 "en", "fi", "fr", "hu", "iw", "nl"
445 for (int i = 0; i < calendarLocales.length; ++i) {
446 String calLocName = calendarLocales[i];
447 Locale calLocale = LocaleUtility.getLocaleFromName(calLocName);
448 cal = new HebrewCalendar(calLocale);
450 for (int j = 0; j < formatLocales.length; ++j) {
451 String locName = formatLocales[j];
452 Locale formatLocale = LocaleUtility.getLocaleFromName(locName);
453 DateFormat format = DateFormat.getDateTimeInstance(cal, DateFormat.FULL, DateFormat.FULL, formatLocale);
454 logln(calLocName + "/" + locName + " --> " + format.format(time));
458 }catch( MissingResourceException ex){
459 warnln("Could not load the locale data. "+ ex.getMessage());
462 public void Test1624() {
464 HebrewCalendar hc = new HebrewCalendar (5742, HebrewCalendar.AV, 22);
465 DateFormat df = hc.getDateTimeFormat(DateFormat.FULL, DateFormat.FULL, Locale.getDefault());
466 String dateString = df.format(hc.getTime());
468 for (int year = 5600; year < 5800; year ++) {
469 boolean leapYear = HebrewCalendar.isLeapYear (year);
470 for (int month = HebrewCalendar.TISHRI; month <= HebrewCalendar.ELUL;month++) {
471 // skip the adar 1 month if year is not a leap year
472 if (leapYear == false && month == HebrewCalendar.ADAR_1) {
476 hc = new HebrewCalendar (year, month, day);
478 dateString = df.format(hc.getTime());
479 int dayHC = hc.get (HebrewCalendar.DATE);
480 int monthHC = hc.get (HebrewCalendar.MONTH);
481 int yearHC = hc.get (HebrewCalendar.YEAR);
483 String header = "year:" + year + " isleap:" + leapYear + " " + dateString;
485 errln (header + " ==> day:" + dayHC + " incorrect, should be:" + day);
488 if (monthHC != month) {
489 errln (header + " ==> month:" + monthHC + " incorrect, should be:" + month);
492 if (yearHC != year) {
493 errln (header + " ==> year:" + yearHC + " incorrecte, should be:" + year);