]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-52_1/main/classes/core/src/com/ibm/icu/util/HebrewCalendar.java
Clean up imports.
[Dictionary.git] / jars / icu4j-52_1 / main / classes / core / src / com / ibm / icu / util / HebrewCalendar.java
1 /*
2  *******************************************************************************
3  * Copyright (C) 1996-2013, International Business Machines Corporation and
4  * others. All Rights Reserved.
5  *******************************************************************************
6  */
7 package com.ibm.icu.util;
8 import java.util.Date;
9 import java.util.Locale;
10
11 import com.ibm.icu.impl.CalendarCache;
12 import com.ibm.icu.util.ULocale.Category;
13
14 /**
15  * <code>HebrewCalendar</code> is a subclass of <code>Calendar</code>
16  * that that implements the traditional Hebrew calendar.
17  * This is the civil calendar in Israel and the liturgical calendar
18  * of the Jewish faith worldwide.
19  * <p>
20  * The Hebrew calendar is lunisolar and thus has a number of interesting
21  * properties that distinguish it from the Gregorian.  Months start
22  * on the day of (an arithmetic approximation of) each new moon.  Since the
23  * solar year (approximately 365.24 days) is not an even multiple of
24  * the lunar month (approximately 29.53 days) an extra "leap month" is
25  * inserted in 7 out of every 19 years.  To make matters even more
26  * interesting, the start of a year can be delayed by up to three days
27  * in order to prevent certain holidays from falling on the Sabbath and
28  * to prevent certain illegal year lengths.  Finally, the lengths of certain
29  * months can vary depending on the number of days in the year.
30  * <p>
31  * The leap month is known as "Adar 1" and is inserted between the
32  * months of Shevat and Adar in leap years.  Since the leap month does
33  * not come at the end of the year, calculations involving
34  * month numbers are particularly complex.  Users of this class should
35  * make sure to use the {@link #roll roll} and {@link #add add} methods
36  * rather than attempting to perform date arithmetic by manipulating
37  * the fields directly.
38  * <p>
39  * <b>Note:</b> In the traditional Hebrew calendar, days start at sunset.
40  * However, in order to keep the time fields in this class
41  * synchronized with those of the other calendars and with local clock time,
42  * we treat days and months as beginning at midnight,
43  * roughly 6 hours after the corresponding sunset.
44  * <p>
45  * If you are interested in more information on the rules behind the Hebrew
46  * calendar, see one of the following references:
47  * <ul>
48  * <li>"<a href="http://www.amazon.com/exec/obidos/ASIN/0521564743">Calendrical Calculations</a>",
49  *      by Nachum Dershowitz & Edward Reingold, Cambridge University Press, 1997, pages 85-91.
50  *
51  * <li>Hebrew Calendar Science and Myths,
52  *      <a href="http://web.archive.org/web/20090423084613/http://www.geocities.com/Athens/1584/">
53  *      http://web.archive.org/web/20090423084613/http://www.geocities.com/Athens/1584/</a>
54  *
55  * <li>The Calendar FAQ,
56  *      <a href="http://www.faqs.org/faqs/calendars/faq/">
57  *      http://www.faqs.org/faqs/calendars/faq/</a>
58  * </ul>
59  *
60  * <p>
61  * This class should not be subclassed.</p>
62  * <p>
63  * HebrewCalendar usually should be instantiated using 
64  * {@link com.ibm.icu.util.Calendar#getInstance(ULocale)} passing in a <code>ULocale</code>
65  * with the tag <code>"@calendar=hebrew"</code>.</p>
66  *
67  * @see com.ibm.icu.util.GregorianCalendar
68  * @see com.ibm.icu.util.Calendar
69  *
70  * @author Laura Werner
71  * @author Alan Liu
72  * @stable ICU 2.8
73  */
74 public class HebrewCalendar extends Calendar {
75     // jdk1.4.2 serialver
76     private static final long serialVersionUID = -1952524560588825816L;
77
78     //-------------------------------------------------------------------------
79     // Tons o' Constants...
80     //-------------------------------------------------------------------------
81
82
83     /** 
84      * Constant for Tishri, the 1st month of the Hebrew year. 
85      * @stable ICU 2.8 
86      */
87     public static final int TISHRI = 0;
88
89     /**
90      * Constant for Heshvan, the 2nd month of the Hebrew year. 
91      * @stable ICU 2.8 
92      */
93     public static final int HESHVAN = 1;
94
95     /**
96      * Constant for Kislev, the 3rd month of the Hebrew year. 
97      * @stable ICU 2.8 
98      */
99     public static final int KISLEV = 2;
100
101     /**
102      * Constant for Tevet, the 4th month of the Hebrew year. 
103      * @stable ICU 2.8 
104      */
105     public static final int TEVET = 3;
106
107     /**
108      * Constant for Shevat, the 5th month of the Hebrew year. 
109      * @stable ICU 2.8 
110      */
111     public static final int SHEVAT = 4;
112
113     /**
114      * Constant for Adar I, the 6th month of the Hebrew year
115      * (present in leap years only). In non-leap years, the calendar
116      * jumps from Shevat (5th month) to Adar (7th month).
117      * @stable ICU 2.8
118      */
119     public static final int ADAR_1 = 5;
120
121     /** 
122      * Constant for the Adar, the 7th month of the Hebrew year. 
123      * @stable ICU 2.8 
124      */
125     public static final int ADAR = 6;
126
127     /**
128      * Constant for Nisan, the 8th month of the Hebrew year. 
129      * @stable ICU 2.8 
130      */
131     public static final int NISAN = 7;
132
133     /**
134      * Constant for Iyar, the 9th month of the Hebrew year. 
135      * @stable ICU 2.8 
136      */
137     public static final int IYAR = 8;
138
139     /**
140      * Constant for Sivan, the 10th month of the Hebrew year. 
141      * @stable ICU 2.8 
142      */
143     public static final int SIVAN = 9;
144
145     /**
146      * Constant for Tammuz, the 11th month of the Hebrew year. 
147      * @stable ICU 2.8 
148      */
149     public static final int TAMUZ = 10;
150
151     /**
152      * Constant for Av, the 12th month of the Hebrew year. 
153      * @stable ICU 2.8 
154      */
155     public static final int AV = 11;
156
157     /**
158      * Constant for Elul, the 13th month of the Hebrew year. 
159      * @stable ICU 2.8 
160      */
161     public static final int ELUL = 12;
162
163     /**
164      * The absolute date, in milliseconds since 1/1/1970 AD, Gregorian,
165      * of the start of the Hebrew calendar.  In order to keep this calendar's
166      * time of day in sync with that of the Gregorian calendar, we use
167      * midnight, rather than sunset the day before.
168      */
169     //private static final long EPOCH_MILLIS = -180799862400000L; // 1/1/1 HY
170
171     private static final int LIMITS[][] = {
172         // Minimum  Greatest    Least  Maximum
173         //           Minimum  Maximum
174         {        0,        0,       0,       0 }, // ERA
175         { -5000000, -5000000, 5000000, 5000000 }, // YEAR
176         {        0,        0,      12,      12 }, // MONTH
177         {        1,        1,      51,      56 }, // WEEK_OF_YEAR
178         {/*                                  */}, // WEEK_OF_MONTH
179         {        1,        1,      29,      30 }, // DAY_OF_MONTH
180         {        1,        1,     353,     385 }, // DAY_OF_YEAR
181         {/*                                  */}, // DAY_OF_WEEK
182         {       -1,       -1,       5,       5 }, // DAY_OF_WEEK_IN_MONTH
183         {/*                                  */}, // AM_PM
184         {/*                                  */}, // HOUR
185         {/*                                  */}, // HOUR_OF_DAY
186         {/*                                  */}, // MINUTE
187         {/*                                  */}, // SECOND
188         {/*                                  */}, // MILLISECOND
189         {/*                                  */}, // ZONE_OFFSET
190         {/*                                  */}, // DST_OFFSET
191         { -5000000, -5000000, 5000000, 5000000 }, // YEAR_WOY
192         {/*                                  */}, // DOW_LOCAL
193         { -5000000, -5000000, 5000000, 5000000 }, // EXTENDED_YEAR
194         {/*                                  */}, // JULIAN_DAY
195         {/*                                  */}, // MILLISECONDS_IN_DAY
196     };
197
198     /**
199      * The lengths of the Hebrew months.  This is complicated, because there
200      * are three different types of years, or six if you count leap years.
201      * Due to the rules for postponing the start of the year to avoid having
202      * certain holidays fall on the sabbath, the year can end up being three
203      * different lengths, called "deficient", "normal", and "complete".
204      */
205     private static final int MONTH_LENGTH[][] = {
206         // Deficient  Normal     Complete
207         {   30,         30,         30     },           //Tishri
208         {   29,         29,         30     },           //Heshvan
209         {   29,         30,         30     },           //Kislev
210         {   29,         29,         29     },           //Tevet
211         {   30,         30,         30     },           //Shevat
212         {   30,         30,         30     },           //Adar I (leap years only)
213         {   29,         29,         29     },           //Adar
214         {   30,         30,         30     },           //Nisan
215         {   29,         29,         29     },           //Iyar
216         {   30,         30,         30     },           //Sivan
217         {   29,         29,         29     },           //Tammuz
218         {   30,         30,         30     },           //Av
219         {   29,         29,         29     },           //Elul
220     };
221
222     /**
223      * The cumulative # of days to the end of each month in a non-leap year
224      * Although this can be calculated from the MONTH_LENGTH table,
225      * keeping it around separately makes some calculations a lot faster
226      */
227     private static final int MONTH_START[][] = {
228         // Deficient  Normal     Complete
229         {    0,          0,          0  },          // (placeholder)
230         {   30,         30,         30  },          // Tishri
231         {   59,         59,         60  },          // Heshvan
232         {   88,         89,         90  },          // Kislev
233         {  117,        118,        119  },          // Tevet
234         {  147,        148,        149  },          // Shevat
235         {  147,        148,        149  },          // (Adar I placeholder)
236         {  176,        177,        178  },          // Adar
237         {  206,        207,        208  },          // Nisan
238         {  235,        236,        237  },          // Iyar
239         {  265,        266,        267  },          // Sivan
240         {  294,        295,        296  },          // Tammuz
241         {  324,        325,        326  },          // Av
242         {  353,        354,        355  },          // Elul
243     };
244
245     /**
246      * The cumulative # of days to the end of each month in a leap year
247      */
248     private static final int LEAP_MONTH_START[][] = {
249         // Deficient  Normal     Complete
250         {    0,          0,          0  },          // (placeholder)
251         {   30,         30,         30  },          // Tishri
252         {   59,         59,         60  },          // Heshvan
253         {   88,         89,         90  },          // Kislev
254         {  117,        118,        119  },          // Tevet
255         {  147,        148,        149  },          // Shevat
256         {  177,        178,        179  },          // Adar I
257         {  206,        207,        208  },          // Adar II
258         {  236,        237,        238  },          // Nisan
259         {  265,        266,        267  },          // Iyar
260         {  295,        296,        297  },          // Sivan
261         {  324,        325,        326  },          // Tammuz
262         {  354,        355,        356  },          // Av
263         {  383,        384,        385  },          // Elul
264     };
265
266     //-------------------------------------------------------------------------
267     // Data Members...
268     //-------------------------------------------------------------------------
269
270     private static CalendarCache cache = new CalendarCache();
271     
272     //-------------------------------------------------------------------------
273     // Constructors...
274     //-------------------------------------------------------------------------
275
276     /**
277      * Constructs a default <code>HebrewCalendar</code> using the current time
278      * in the default time zone with the default <code>FORMAT</code> locale.
279      * @see Category#FORMAT
280      * @stable ICU 2.8
281      */
282     public HebrewCalendar() {
283         this(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT));
284     }
285
286     /**
287      * Constructs a <code>HebrewCalendar</code> based on the current time
288      * in the given time zone with the default <code>FORMAT</code> locale.
289      *
290      * @param zone The time zone for the new calendar.
291      * @see Category#FORMAT
292      * @stable ICU 2.8
293      */
294     public HebrewCalendar(TimeZone zone) {
295         this(zone, ULocale.getDefault(Category.FORMAT));
296     }
297
298     /**
299      * Constructs a <code>HebrewCalendar</code> based on the current time
300      * in the default time zone with the given locale.
301      *
302      * @param aLocale The locale for the new calendar.
303      * @stable ICU 2.8
304      */
305     public HebrewCalendar(Locale aLocale) {
306         this(TimeZone.getDefault(), aLocale);
307     }
308
309     /**
310      * Constructs a <code>HebrewCalendar</code> based on the current time
311      * in the default time zone with the given locale.
312      *
313      * @param locale The locale for the new calendar.
314      * @stable ICU 3.2
315      */
316     public HebrewCalendar(ULocale locale) {
317         this(TimeZone.getDefault(), locale);
318     }
319
320     /**
321      * Constructs a <code>HebrewCalendar</code> based on the current time
322      * in the given time zone with the given locale.
323      *
324      * @param zone The time zone for the new calendar.
325      *
326      * @param aLocale The locale for the new calendar.
327      * @stable ICU 2.8
328      */
329     public HebrewCalendar(TimeZone zone, Locale aLocale) {
330         super(zone, aLocale);
331         setTimeInMillis(System.currentTimeMillis());
332     }
333
334     /**
335      * Constructs a <code>HebrewCalendar</code> based on the current time
336      * in the given time zone with the given locale.
337      *
338      * @param zone The time zone for the new calendar.
339      *
340      * @param locale The locale for the new calendar.
341      * @stable ICU 3.2
342      */
343     public HebrewCalendar(TimeZone zone, ULocale locale) {
344         super(zone, locale);
345         setTimeInMillis(System.currentTimeMillis());
346     }
347
348     /**
349      * Constructs a <code>HebrewCalendar</code> with the given date set
350      * in the default time zone with the default <code>FORMAT</code> locale.
351      *
352      * @param year      The value used to set the calendar's {@link #YEAR YEAR} time field.
353      *
354      * @param month     The value used to set the calendar's {@link #MONTH MONTH} time field.
355      *                  The value is 0-based. e.g., 0 for Tishri.
356      *
357      * @param date      The value used to set the calendar's {@link #DATE DATE} time field.
358      * @see Category#FORMAT
359      * @stable ICU 2.8
360      */
361     public HebrewCalendar(int year, int month, int date) {
362         super(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT));
363         this.set(YEAR, year);
364         this.set(MONTH, month);
365         this.set(DATE, date);
366     }
367
368     /**
369      * Constructs a <code>HebrewCalendar</code> with the given date set
370      * in the default time zone with the default <code>FORMAT</code> locale.
371      *
372      * @param date      The date to which the new calendar is set.
373      * @see Category#FORMAT
374      * @stable ICU 2.8
375      */
376     public HebrewCalendar(Date date) {
377         super(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT));
378         this.setTime(date);
379     }
380
381     /**
382      * Constructs a <code>HebrewCalendar</code> with the given date
383      * and time set for the default time zone with the default <code>FORMAT</code> locale.
384      *
385      * @param year      The value used to set the calendar's {@link #YEAR YEAR} time field.
386      *
387      * @param month     The value used to set the calendar's {@link #MONTH MONTH} time field.
388      *                  The value is 0-based. e.g., 0 for Tishri.
389      *
390      * @param date      The value used to set the calendar's {@link #DATE DATE} time field.
391      *
392      * @param hour      The value used to set the calendar's {@link #HOUR_OF_DAY HOUR_OF_DAY} time field.
393      *
394      * @param minute    The value used to set the calendar's {@link #MINUTE MINUTE} time field.
395      *
396      * @param second    The value used to set the calendar's {@link #SECOND SECOND} time field.
397      * @see Category#FORMAT
398      * @stable ICU 2.8
399      */
400     public HebrewCalendar(int year, int month, int date, int hour,
401                              int minute, int second)
402     {
403         super(TimeZone.getDefault(), ULocale.getDefault(Category.FORMAT));
404         this.set(YEAR, year);
405         this.set(MONTH, month);
406         this.set(DATE, date);
407         this.set(HOUR_OF_DAY, hour);
408         this.set(MINUTE, minute);
409         this.set(SECOND, second);
410     }
411
412     //-------------------------------------------------------------------------
413     // Rolling and adding functions overridden from Calendar
414     //
415     // These methods call through to the default implementation in IBMCalendar
416     // for most of the fields and only handle the unusual ones themselves.
417     //-------------------------------------------------------------------------
418
419     /**
420      * Add a signed amount to a specified field, using this calendar's rules.
421      * For example, to add three days to the current date, you can call
422      * <code>add(Calendar.DATE, 3)</code>. 
423      * <p>
424      * When adding to certain fields, the values of other fields may conflict and
425      * need to be changed.  For example, when adding one to the {@link #MONTH MONTH} field
426      * for the date "30 Av 5758", the {@link #DAY_OF_MONTH DAY_OF_MONTH} field
427      * must be adjusted so that the result is "29 Elul 5758" rather than the invalid
428      * "30 Elul 5758".
429      * <p>
430      * This method is able to add to
431      * all fields except for {@link #ERA ERA}, {@link #DST_OFFSET DST_OFFSET},
432      * and {@link #ZONE_OFFSET ZONE_OFFSET}.
433      * <p>
434      * <b>Note:</b> You should always use {@link #roll roll} and add rather
435      * than attempting to perform arithmetic operations directly on the fields
436      * of a <tt>HebrewCalendar</tt>.  Since the {@link #MONTH MONTH} field behaves
437      * discontinuously in non-leap years, simple arithmetic can give invalid results.
438      * <p>
439      * @param field     the time field.
440      * @param amount    the amount to add to the field.
441      *
442      * @exception   IllegalArgumentException if the field is invalid or refers
443      *              to a field that cannot be handled by this method.
444      * @stable ICU 2.8
445      */
446     public void add(int field, int amount)
447     {
448         switch (field) {
449         case MONTH: 
450             {
451                 // We can't just do a set(MONTH, get(MONTH) + amount).  The
452                 // reason is ADAR_1.  Suppose amount is +2 and we land in
453                 // ADAR_1 -- then we have to bump to ADAR_2 aka ADAR.  But
454                 // if amount is -2 and we land in ADAR_1, then we have to
455                 // bump the other way -- down to SHEVAT.  - Alan 11/00
456                 int month = get(MONTH);
457                 int year = get(YEAR);
458                 boolean acrossAdar1;
459                 if (amount > 0) {
460                     acrossAdar1 = (month < ADAR_1); // started before ADAR_1?
461                     month += amount;
462                     for (;;) {
463                         if (acrossAdar1 && month>=ADAR_1 && !isLeapYear(year)) {
464                             ++month;
465                         }
466                         if (month <= ELUL) {
467                             break;
468                         }
469                         month -= ELUL+1;
470                         ++year;
471                         acrossAdar1 = true;
472                     }
473                 } else {
474                     acrossAdar1 = (month > ADAR_1); // started after ADAR_1?
475                     month += amount;
476                     for (;;) {
477                         if (acrossAdar1 && month<=ADAR_1 && !isLeapYear(year)) {
478                             --month;
479                         }
480                         if (month >= 0) {
481                             break;
482                         }
483                         month += ELUL+1;
484                         --year;
485                         acrossAdar1 = true;
486                     }
487                 }
488                 set(MONTH, month);
489                 set(YEAR, year);
490                 pinField(DAY_OF_MONTH);
491                 break;
492             }
493             
494         default:
495             super.add(field, amount);
496             break;
497         }
498     }
499
500     /**
501      * Rolls (up/down) a specified amount time on the given field.  For
502      * example, to roll the current date up by three days, you can call
503      * <code>roll(Calendar.DATE, 3)</code>.  If the
504      * field is rolled past its maximum allowable value, it will "wrap" back
505      * to its minimum and continue rolling.  
506      * For example, calling <code>roll(Calendar.DATE, 10)</code>
507      * on a Hebrew calendar set to "25 Av 5758" will result in the date "5 Av 5758".
508      * <p>
509      * When rolling certain fields, the values of other fields may conflict and
510      * need to be changed.  For example, when rolling the {@link #MONTH MONTH} field
511      * upward by one for the date "30 Av 5758", the {@link #DAY_OF_MONTH DAY_OF_MONTH} field
512      * must be adjusted so that the result is "29 Elul 5758" rather than the invalid
513      * "30 Elul".
514      * <p>
515      * This method is able to roll
516      * all fields except for {@link #ERA ERA}, {@link #DST_OFFSET DST_OFFSET},
517      * and {@link #ZONE_OFFSET ZONE_OFFSET}.  Subclasses may, of course, add support for
518      * additional fields in their overrides of <code>roll</code>.
519      * <p>
520      * <b>Note:</b> You should always use roll and {@link #add add} rather
521      * than attempting to perform arithmetic operations directly on the fields
522      * of a <tt>HebrewCalendar</tt>.  Since the {@link #MONTH MONTH} field behaves
523      * discontinuously in non-leap years, simple arithmetic can give invalid results.
524      * <p>
525      * @param field     the time field.
526      * @param amount    the amount by which the field should be rolled.
527      *
528      * @exception   IllegalArgumentException if the field is invalid or refers
529      *              to a field that cannot be handled by this method.
530      * @stable ICU 2.8
531      */
532     public void roll(int field, int amount)
533     {
534         switch (field) {
535         case MONTH:
536             {
537                 int month = get(MONTH);
538                 int year = get(YEAR);
539                 
540                 boolean leapYear = isLeapYear(year);
541                 int yearLength = monthsInYear(year);
542                 int newMonth = month + (amount % yearLength);
543                 //
544                 // If it's not a leap year and we're rolling past the missing month
545                 // of ADAR_1, we need to roll an extra month to make up for it.
546                 //
547                 if (!leapYear) {
548                     if (amount > 0 && month < ADAR_1 && newMonth >= ADAR_1) {
549                         newMonth++;
550                     } else if (amount < 0 && month > ADAR_1 && newMonth <= ADAR_1) {
551                         newMonth--;
552                     }
553                 }
554                 set(MONTH, (newMonth + 13) % 13);
555                 pinField(DAY_OF_MONTH);
556                 return;
557             }
558         default:
559             super.roll(field, amount);
560         }
561     }
562
563     //-------------------------------------------------------------------------
564     // Support methods
565     //-------------------------------------------------------------------------
566
567     // Hebrew date calculations are performed in terms of days, hours, and
568     // "parts" (or halakim), which are 1/1080 of an hour, or 3 1/3 seconds.
569     private static final long HOUR_PARTS = 1080;
570     private static final long DAY_PARTS  = 24*HOUR_PARTS;
571     
572     // An approximate value for the length of a lunar month.
573     // It is used to calculate the approximate year and month of a given
574     // absolute date.
575     static private final int  MONTH_DAYS = 29;
576     static private final long MONTH_FRACT = 12*HOUR_PARTS + 793;
577     static private final long MONTH_PARTS = MONTH_DAYS*DAY_PARTS + MONTH_FRACT;
578     
579     // The time of the new moon (in parts) on 1 Tishri, year 1 (the epoch)
580     // counting from noon on the day before.  BAHARAD is an abbreviation of
581     // Bet (Monday), Hey (5 hours from sunset), Resh-Daled (204).
582     static private final long BAHARAD = 11*HOUR_PARTS + 204;
583
584     /**
585      * Finds the day # of the first day in the given Hebrew year.
586      * To do this, we want to calculate the time of the Tishri 1 new moon
587      * in that year.
588      * <p>
589      * The algorithm here is similar to ones described in a number of
590      * references, including:
591      * <ul>
592      * <li>"Calendrical Calculations", by Nachum Dershowitz & Edward Reingold,
593      *     Cambridge University Press, 1997, pages 85-91.
594      *
595      * <li>Hebrew Calendar Science and Myths,
596      *     <a href="http://www.geocities.com/Athens/1584/">
597      *     http://www.geocities.com/Athens/1584/</a>
598      *
599      * <li>The Calendar FAQ,
600      *      <a href="http://www.faqs.org/faqs/calendars/faq/">
601      *      http://www.faqs.org/faqs/calendars/faq/</a>
602      * </ul>
603      */
604     private static long startOfYear(int year)
605     {
606         long day = cache.get(year);
607         
608         if (day == CalendarCache.EMPTY) {
609             int months = (235 * year - 234) / 19;           // # of months before year
610
611             long frac = months * MONTH_FRACT + BAHARAD;     // Fractional part of day #
612             day  = months * 29 + (frac / DAY_PARTS);        // Whole # part of calculation
613             frac = frac % DAY_PARTS;                        // Time of day
614
615             int wd = (int)(day % 7);                        // Day of week (0 == Monday)
616
617             if (wd == 2 || wd == 4 || wd == 6) {
618                 // If the 1st is on Sun, Wed, or Fri, postpone to the next day
619                 day += 1;
620                 wd = (int)(day % 7);
621             }
622             if (wd == 1 && frac > 15*HOUR_PARTS+204 && !isLeapYear(year) ) {
623                 // If the new moon falls after 3:11:20am (15h204p from the previous noon)
624                 // on a Tuesday and it is not a leap year, postpone by 2 days.
625                 // This prevents 356-day years.
626                 day += 2;
627             }
628             else if (wd == 0 && frac > 21*HOUR_PARTS+589 && isLeapYear(year-1) ) {
629                 // If the new moon falls after 9:32:43 1/3am (21h589p from yesterday noon)
630                 // on a Monday and *last* year was a leap year, postpone by 1 day.
631                 // Prevents 382-day years.
632                 day += 1;
633             }
634             cache.put(year, day);
635         }
636         return day;
637     }
638
639     /*
640      * Find the day of the week for a given day
641      *
642      * @param day   The # of days since the start of the Hebrew calendar,
643      *              1-based (i.e. 1/1/1 AM is day 1).
644      */
645     /*private static int absoluteDayToDayOfWeek(long day)
646     {
647         // We know that 1/1/1 AM is a Monday, which makes the math easy...
648         return (int)(day % 7) + 1;
649     }*/
650
651     /**
652      * Returns the the type of a given year.
653      *  0   "Deficient" year with 353 or 383 days
654      *  1   "Normal"    year with 354 or 384 days
655      *  2   "Complete"  year with 355 or 385 days
656      */
657     private final int yearType(int year)
658     {
659         int yearLength = handleGetYearLength(year);
660
661         if (yearLength > 380) {
662            yearLength -= 30;        // Subtract length of leap month.
663         }
664
665         int type = 0;
666
667         switch (yearLength) {
668             case 353:
669                 type = 0; break;
670             case 354:
671                 type = 1; break;
672             case 355:
673                 type = 2; break;
674             default:
675                 throw new IllegalArgumentException("Illegal year length " + yearLength + " in year " + year);
676
677         }
678         return type;
679     }
680
681     /**
682      * Determine whether a given Hebrew year is a leap year
683      *
684      * The rule here is that if (year % 19) == 0, 3, 6, 8, 11, 14, or 17.
685      * The formula below performs the same test, believe it or not.
686      * @internal
687      * @deprecated This API is ICU internal only.
688      */
689     public static boolean isLeapYear(int year) {
690         //return (year * 12 + 17) % 19 >= 12;
691         int x = (year*12 + 17) % 19;
692         return x >= ((x < 0) ? -7 : 12);
693     }
694
695     private static int monthsInYear(int year) {
696         return isLeapYear(year) ? 13 : 12;
697     }
698
699     //-------------------------------------------------------------------------
700     // Calendar framework
701     //-------------------------------------------------------------------------
702
703     /**
704      * @stable ICU 2.8
705      */
706     protected int handleGetLimit(int field, int limitType) {
707         return LIMITS[field][limitType];
708     }
709
710     /**
711      * Returns the length of the given month in the given year
712      * @stable ICU 2.8
713      */
714     protected int handleGetMonthLength(int extendedYear, int month) {
715         // Resolve out-of-range months.  This is necessary in order to
716         // obtain the correct year.  We correct to
717         // a 12- or 13-month year (add/subtract 12 or 13, depending
718         // on the year) but since we _always_ number from 0..12, and
719         // the leap year determines whether or not month 5 (Adar 1)
720         // is present, we allow 0..12 in any given year.
721         while (month < 0) {
722             month += monthsInYear(--extendedYear);
723         }
724         // Careful: allow 0..12 in all years
725         while (month > 12) {
726             month -= monthsInYear(extendedYear++);
727         }
728
729         switch (month) {
730             case HESHVAN:
731             case KISLEV:
732                 // These two month lengths can vary
733                 return MONTH_LENGTH[month][yearType(extendedYear)];
734                 
735             default:
736                 // The rest are a fixed length
737                 return MONTH_LENGTH[month][0];
738         }
739     }
740
741     /**
742      * Returns the number of days in the given Hebrew year
743      * @stable ICU 2.8
744      */
745     protected int handleGetYearLength(int eyear) {
746         return (int)(startOfYear(eyear+1) - startOfYear(eyear));
747     }
748
749     //-------------------------------------------------------------------------
750     // Functions for converting from milliseconds to field values
751     //-------------------------------------------------------------------------
752
753     /**
754      * Subclasses may override this method to compute several fields
755      * specific to each calendar system.  These are:
756      *
757      * <ul><li>ERA
758      * <li>YEAR
759      * <li>MONTH
760      * <li>DAY_OF_MONTH
761      * <li>DAY_OF_YEAR
762      * <li>EXTENDED_YEAR</ul>
763      * 
764      * Subclasses can refer to the DAY_OF_WEEK and DOW_LOCAL fields,
765      * which will be set when this method is called.  Subclasses can
766      * also call the getGregorianXxx() methods to obtain Gregorian
767      * calendar equivalents for the given Julian day.
768      *
769      * <p>In addition, subclasses should compute any subclass-specific
770      * fields, that is, fields from BASE_FIELD_COUNT to
771      * getFieldCount() - 1.
772      * @stable ICU 2.8
773      */
774     protected void handleComputeFields(int julianDay) {
775         long d = julianDay - 347997;
776         long m = (d * DAY_PARTS) / MONTH_PARTS;         // Months (approx)
777         int year = (int)((19 * m + 234) / 235) + 1;     // Years (approx)
778         long ys  = startOfYear(year);                   // 1st day of year
779         int dayOfYear = (int)(d - ys);
780
781         // Because of the postponement rules, it's possible to guess wrong.  Fix it.
782         while (dayOfYear < 1) {
783             year--;
784             ys  = startOfYear(year);
785             dayOfYear = (int)(d - ys);
786         }
787
788         // Now figure out which month we're in, and the date within that month
789         int yearType = yearType(year);
790         int monthStart[][] = isLeapYear(year) ? LEAP_MONTH_START : MONTH_START;
791
792         int month = 0;
793         while (dayOfYear > monthStart[month][yearType]) {
794             month++;
795         }
796         month--;
797         int dayOfMonth = dayOfYear - monthStart[month][yearType];
798
799         internalSet(ERA, 0);
800         internalSet(YEAR, year);
801         internalSet(EXTENDED_YEAR, year);
802         internalSet(MONTH, month);
803         internalSet(DAY_OF_MONTH, dayOfMonth);
804         internalSet(DAY_OF_YEAR, dayOfYear);       
805     }
806
807     //-------------------------------------------------------------------------
808     // Functions for converting from field values to milliseconds
809     //-------------------------------------------------------------------------
810
811     /**
812      * @stable ICU 2.8
813      */
814     protected int handleGetExtendedYear() {
815         int year;
816         if (newerField(EXTENDED_YEAR, YEAR) == EXTENDED_YEAR) {
817             year = internalGet(EXTENDED_YEAR, 1); // Default to year 1
818         } else {
819             year = internalGet(YEAR, 1); // Default to year 1
820         }
821         return year;
822     }
823
824     /**
825      * Return JD of start of given month/year.
826      * @stable ICU 2.8
827      */
828     protected int handleComputeMonthStart(int eyear, int month, boolean useMonth) {
829
830         // Resolve out-of-range months.  This is necessary in order to
831         // obtain the correct year.  We correct to
832         // a 12- or 13-month year (add/subtract 12 or 13, depending
833         // on the year) but since we _always_ number from 0..12, and
834         // the leap year determines whether or not month 5 (Adar 1)
835         // is present, we allow 0..12 in any given year.
836         while (month < 0) {
837             month += monthsInYear(--eyear);
838         }
839         // Careful: allow 0..12 in all years
840         while (month > 12) {
841             month -= monthsInYear(eyear++);
842         }
843
844         long day = startOfYear(eyear);
845
846         if (month != 0) {
847             if (isLeapYear(eyear)) {
848                 day += LEAP_MONTH_START[month][yearType(eyear)];
849             } else {
850                 day += MONTH_START[month][yearType(eyear)];
851             }
852         }
853
854         return (int) (day + 347997);
855     }
856
857     /**
858      * {@inheritDoc}
859      * @stable ICU 3.8
860      */
861     public String getType() {
862         return "hebrew";
863     }
864
865     /*
866     private static CalendarFactory factory;
867     public static CalendarFactory factory() {
868         if (factory == null) {
869             factory = new CalendarFactory() {
870                 public Calendar create(TimeZone tz, ULocale loc) {
871                     return new HebrewCalendar(tz, loc);
872                 }
873
874                 public String factoryName() {
875                     return "Hebrew";
876                 }
877             };
878         }
879         return factory;
880     }
881     */
882 }