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