]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_4_2-src/main/classes/core/src/com/ibm/icu/util/IslamicCalendar.java
go
[Dictionary.git] / jars / icu4j-4_4_2-src / main / classes / core / src / com / ibm / icu / util / IslamicCalendar.java
1 /*\r
2  *******************************************************************************\r
3  * Copyright (C) 1996-2010, International Business Machines Corporation and    *\r
4  * others. All Rights Reserved.                                                *\r
5  *******************************************************************************\r
6  */\r
7 package com.ibm.icu.util;\r
8 import java.util.Date;\r
9 import java.util.Locale;\r
10 \r
11 import com.ibm.icu.impl.CalendarAstronomer;\r
12 import com.ibm.icu.impl.CalendarCache;\r
13 \r
14 /**\r
15  * <code>IslamicCalendar</code> is a subclass of <code>Calendar</code>\r
16  * that that implements the Islamic civil and religious calendars.  It\r
17  * is used as the civil calendar in most of the Arab world and the\r
18  * liturgical calendar of the Islamic faith worldwide.  This calendar\r
19  * is also known as the "Hijri" calendar, since it starts at the time\r
20  * of Mohammed's emigration (or "hijra") to Medinah on Thursday, \r
21  * July 15, 622 AD (Julian).\r
22  * <p>\r
23  * The Islamic calendar is strictly lunar, and thus an Islamic year of twelve\r
24  * lunar months does not correspond to the solar year used by most other\r
25  * calendar systems, including the Gregorian.  An Islamic year is, on average,\r
26  * about 354 days long, so each successive Islamic year starts about 11 days\r
27  * earlier in the corresponding Gregorian year.\r
28  * <p>\r
29  * Each month of the calendar starts when the new moon's crescent is visible\r
30  * at sunset.  However, in order to keep the time fields in this class\r
31  * synchronized with those of the other calendars and with local clock time,\r
32  * we treat days and months as beginning at midnight,\r
33  * roughly 6 hours after the corresponding sunset.\r
34  * <p>\r
35  * There are two main variants of the Islamic calendar in existence.  The first\r
36  * is the <em>civil</em> calendar, which uses a fixed cycle of alternating 29-\r
37  * and 30-day months, with a leap day added to the last month of 11 out of\r
38  * every 30 years.  This calendar is easily calculated and thus predictable in\r
39  * advance, so it is used as the civil calendar in a number of Arab countries.\r
40  * This is the default behavior of a newly-created <code>IslamicCalendar</code>\r
41  * object.\r
42  * <p>\r
43  * The Islamic <em>religious</em> calendar, however, is based on the <em>observation</em>\r
44  * of the crescent moon.  It is thus affected by the position at which the\r
45  * observations are made, seasonal variations in the time of sunset, the\r
46  * eccentricities of the moon's orbit, and even the weather at the observation\r
47  * site.  This makes it impossible to calculate in advance, and it causes the\r
48  * start of a month in the religious calendar to differ from the civil calendar\r
49  * by up to three days.\r
50  * <p>\r
51  * Using astronomical calculations for the position of the sun and moon, the\r
52  * moon's illumination, and other factors, it is possible to determine the start\r
53  * of a lunar month with a fairly high degree of certainty.  However, these\r
54  * calculations are extremely complicated and thus slow, so most algorithms,\r
55  * including the one used here, are only approximations of the true astronical\r
56  * calculations.  At present, the approximations used in this class are fairly\r
57  * simplistic; they will be improved in later versions of the code.\r
58  * <p>\r
59  * The {@link #setCivil setCivil} method determines\r
60  * which approach is used to determine the start of a month.  By default, the\r
61  * fixed-cycle civil calendar is used.  However, if <code>setCivil(false)</code>\r
62  * is called, an approximation of the true lunar calendar will be used.\r
63  * <p>\r
64  * This class should not be subclassed.</p>\r
65  * <p>\r
66  * IslamicCalendar usually should be instantiated using \r
67  * {@link com.ibm.icu.util.Calendar#getInstance(ULocale)} passing in a <code>ULocale</code>\r
68  * with the tag <code>"@calendar=islamic"</code> or <code>"@calendar=islamic-civil"</code>.</p>\r
69  *\r
70  * @see com.ibm.icu.util.GregorianCalendar\r
71  * @see com.ibm.icu.util.Calendar\r
72  *\r
73  * @author Laura Werner\r
74  * @author Alan Liu\r
75  * @stable ICU 2.8\r
76  */\r
77 public class IslamicCalendar extends Calendar {\r
78     // jdk1.4.2 serialver\r
79     private static final long serialVersionUID = -6253365474073869325L;\r
80 \r
81     //-------------------------------------------------------------------------\r
82     // Constants...\r
83     //-------------------------------------------------------------------------\r
84     \r
85     /**\r
86      * Constant for Muharram, the 1st month of the Islamic year. \r
87      * @stable ICU 2.8 \r
88      */\r
89     public static final int MUHARRAM = 0;\r
90 \r
91     /**\r
92      * Constant for Safar, the 2nd month of the Islamic year. \r
93      * @stable ICU 2.8 \r
94      */\r
95     public static final int SAFAR = 1;\r
96 \r
97     /**\r
98      * Constant for Rabi' al-awwal (or Rabi' I), the 3rd month of the Islamic year. \r
99      * @stable ICU 2.8 \r
100      */\r
101     public static final int RABI_1 = 2;\r
102 \r
103     /**\r
104      * Constant for Rabi' al-thani or (Rabi' II), the 4th month of the Islamic year. \r
105      * @stable ICU 2.8 \r
106      */\r
107     public static final int RABI_2 = 3;\r
108 \r
109     /**\r
110      * Constant for Jumada al-awwal or (Jumada I), the 5th month of the Islamic year. \r
111      * @stable ICU 2.8 \r
112      */\r
113     public static final int JUMADA_1 = 4;\r
114 \r
115     /**\r
116      * Constant for Jumada al-thani or (Jumada II), the 6th month of the Islamic year. \r
117      * @stable ICU 2.8 \r
118      */\r
119     public static final int JUMADA_2 = 5;\r
120 \r
121     /**\r
122      * Constant for Rajab, the 7th month of the Islamic year. \r
123      * @stable ICU 2.8 \r
124      */\r
125     public static final int RAJAB = 6;\r
126 \r
127     /**\r
128      * Constant for Sha'ban, the 8th month of the Islamic year. \r
129      * @stable ICU 2.8 \r
130      */\r
131     public static final int SHABAN = 7;\r
132 \r
133     /**\r
134      * Constant for Ramadan, the 9th month of the Islamic year. \r
135      * @stable ICU 2.8 \r
136      */\r
137     public static final int RAMADAN = 8;\r
138 \r
139     /**\r
140      * Constant for Shawwal, the 10th month of the Islamic year. \r
141      * @stable ICU 2.8 \r
142      */\r
143     public static final int SHAWWAL = 9;\r
144 \r
145     /**\r
146      * Constant for Dhu al-Qi'dah, the 11th month of the Islamic year. \r
147      * @stable ICU 2.8 \r
148      */\r
149     public static final int DHU_AL_QIDAH = 10;\r
150 \r
151     /**\r
152      * Constant for Dhu al-Hijjah, the 12th month of the Islamic year. \r
153      * @stable ICU 2.8 \r
154      */\r
155     public static final int DHU_AL_HIJJAH = 11;\r
156 \r
157 \r
158     private static final long HIJRA_MILLIS = -42521587200000L;    // 7/16/622 AD 00:00\r
159 \r
160     //-------------------------------------------------------------------------\r
161     // Constructors...\r
162     //-------------------------------------------------------------------------\r
163 \r
164     /**\r
165      * Constructs a default <code>IslamicCalendar</code> using the current time\r
166      * in the default time zone with the default locale.\r
167      * @stable ICU 2.8\r
168      */\r
169     public IslamicCalendar()\r
170     {\r
171         this(TimeZone.getDefault(), ULocale.getDefault());\r
172     }\r
173 \r
174     /**\r
175      * Constructs an <code>IslamicCalendar</code> based on the current time\r
176      * in the given time zone with the default locale.\r
177      * @param zone the given time zone.\r
178      * @stable ICU 2.8\r
179      */\r
180     public IslamicCalendar(TimeZone zone)\r
181     {\r
182         this(zone, ULocale.getDefault());\r
183     }\r
184 \r
185     /**\r
186      * Constructs an <code>IslamicCalendar</code> based on the current time\r
187      * in the default time zone with the given locale.\r
188      *\r
189      * @param aLocale the given locale.\r
190      * @stable ICU 2.8\r
191      */\r
192     public IslamicCalendar(Locale aLocale)\r
193     {\r
194         this(TimeZone.getDefault(), aLocale);\r
195     }\r
196 \r
197     /**\r
198      * Constructs an <code>IslamicCalendar</code> based on the current time\r
199      * in the default time zone with the given locale.\r
200      *\r
201      * @param locale the given ulocale.\r
202      * @stable ICU 3.2\r
203      */\r
204     public IslamicCalendar(ULocale locale)\r
205     {\r
206         this(TimeZone.getDefault(), locale);\r
207     }\r
208 \r
209     /**\r
210      * Constructs an <code>IslamicCalendar</code> based on the current time\r
211      * in the given time zone with the given locale.\r
212      *\r
213      * @param zone the given time zone.\r
214      * @param aLocale the given locale.\r
215      * @stable ICU 2.8\r
216      */\r
217     public IslamicCalendar(TimeZone zone, Locale aLocale)\r
218     {\r
219         super(zone, aLocale);\r
220         setTimeInMillis(System.currentTimeMillis());\r
221     }\r
222 \r
223     /**\r
224      * Constructs an <code>IslamicCalendar</code> based on the current time\r
225      * in the given time zone with the given locale.\r
226      *\r
227      * @param zone the given time zone.\r
228      * @param locale the given ulocale.\r
229      * @stable ICU 3.2\r
230      */\r
231     public IslamicCalendar(TimeZone zone, ULocale locale)\r
232     {\r
233         super(zone, locale);\r
234         setTimeInMillis(System.currentTimeMillis());\r
235     }\r
236 \r
237     /**\r
238      * Constructs an <code>IslamicCalendar</code> with the given date set\r
239      * in the default time zone with the default locale.\r
240      *\r
241      * @param date      The date to which the new calendar is set.\r
242      * @stable ICU 2.8\r
243      */\r
244     public IslamicCalendar(Date date) {\r
245         super(TimeZone.getDefault(), ULocale.getDefault());\r
246         this.setTime(date);\r
247     }\r
248 \r
249     /**\r
250      * Constructs an <code>IslamicCalendar</code> with the given date set\r
251      * in the default time zone with the default locale.\r
252      *\r
253      * @param year the value used to set the {@link #YEAR YEAR} time field in the calendar.\r
254      * @param month the value used to set the {@link #MONTH MONTH} time field in the calendar.\r
255      *              Note that the month value is 0-based. e.g., 0 for Muharram.\r
256      * @param date the value used to set the {@link #DATE DATE} time field in the calendar.\r
257      * @stable ICU 2.8\r
258      */\r
259     public IslamicCalendar(int year, int month, int date)\r
260     {\r
261         super(TimeZone.getDefault(), ULocale.getDefault());\r
262         this.set(Calendar.YEAR, year);\r
263         this.set(Calendar.MONTH, month);\r
264         this.set(Calendar.DATE, date);\r
265     }\r
266 \r
267     /**\r
268      * Constructs an <code>IslamicCalendar</code> with the given date\r
269      * and time set for the default time zone with the default locale.\r
270      *\r
271      * @param year  the value used to set the {@link #YEAR YEAR} time field in the calendar.\r
272      * @param month the value used to set the {@link #MONTH MONTH} time field in the calendar.\r
273      *              Note that the month value is 0-based. e.g., 0 for Muharram.\r
274      * @param date  the value used to set the {@link #DATE DATE} time field in the calendar.\r
275      * @param hour  the value used to set the {@link #HOUR_OF_DAY HOUR_OF_DAY} time field\r
276      *              in the calendar.\r
277      * @param minute the value used to set the {@link #MINUTE MINUTE} time field\r
278      *              in the calendar.\r
279      * @param second the value used to set the {@link #SECOND SECOND} time field\r
280      *              in the calendar.\r
281      * @stable ICU 2.8\r
282      */\r
283     public IslamicCalendar(int year, int month, int date, int hour,\r
284                              int minute, int second)\r
285     {\r
286         super(TimeZone.getDefault(), ULocale.getDefault());\r
287         this.set(Calendar.YEAR, year);\r
288         this.set(Calendar.MONTH, month);\r
289         this.set(Calendar.DATE, date);\r
290         this.set(Calendar.HOUR_OF_DAY, hour);\r
291         this.set(Calendar.MINUTE, minute);\r
292         this.set(Calendar.SECOND, second);\r
293     }\r
294 \r
295     /**\r
296      * Determines whether this object uses the fixed-cycle Islamic civil calendar\r
297      * or an approximation of the religious, astronomical calendar.\r
298      *\r
299      * @param beCivil   <code>true</code> to use the civil calendar,\r
300      *                  <code>false</code> to use the astronomical calendar.\r
301      * @stable ICU 2.8\r
302      */\r
303     public void setCivil(boolean beCivil)\r
304     {\r
305         if (civil != beCivil) {\r
306             // The fields of the calendar will become invalid, because the calendar\r
307             // rules are different\r
308             long m = getTimeInMillis();\r
309             civil = beCivil;\r
310             clear();\r
311             setTimeInMillis(m);\r
312         }\r
313     }\r
314     \r
315     /**\r
316      * Returns <code>true</code> if this object is using the fixed-cycle civil\r
317      * calendar, or <code>false</code> if using the religious, astronomical\r
318      * calendar.\r
319      * @stable ICU 2.8\r
320      */\r
321     public boolean isCivil() {\r
322         return civil;\r
323     }\r
324     \r
325     //-------------------------------------------------------------------------\r
326     // Minimum / Maximum access functions\r
327     //-------------------------------------------------------------------------\r
328 \r
329     // Note: Current IslamicCalendar implementation does not work\r
330     // well with negative years.\r
331 \r
332     private static final int LIMITS[][] = {\r
333         // Minimum  Greatest     Least   Maximum\r
334         //           Minimum   Maximum\r
335         {        0,        0,        0,        0}, // ERA\r
336         {        1,        1,  5000000,  5000000}, // YEAR\r
337         {        0,        0,       11,       11}, // MONTH\r
338         {        1,        1,       50,       51}, // WEEK_OF_YEAR\r
339         {/*                                   */}, // WEEK_OF_MONTH\r
340         {        1,        1,       29,       30}, // DAY_OF_MONTH\r
341         {        1,        1,      354,      355}, // DAY_OF_YEAR\r
342         {/*                                   */}, // DAY_OF_WEEK\r
343         {       -1,       -1,        5,        5}, // DAY_OF_WEEK_IN_MONTH\r
344         {/*                                   */}, // AM_PM\r
345         {/*                                   */}, // HOUR\r
346         {/*                                   */}, // HOUR_OF_DAY\r
347         {/*                                   */}, // MINUTE\r
348         {/*                                   */}, // SECOND\r
349         {/*                                   */}, // MILLISECOND\r
350         {/*                                   */}, // ZONE_OFFSET\r
351         {/*                                   */}, // DST_OFFSET\r
352         {        1,        1,  5000000,  5000000}, // YEAR_WOY\r
353         {/*                                   */}, // DOW_LOCAL\r
354         {        1,        1,  5000000,  5000000}, // EXTENDED_YEAR\r
355         {/*                                   */}, // JULIAN_DAY\r
356         {/*                                   */}, // MILLISECONDS_IN_DAY\r
357     };\r
358 \r
359     /**\r
360      * @stable ICU 2.8\r
361      */\r
362     protected int handleGetLimit(int field, int limitType) {\r
363         return LIMITS[field][limitType];\r
364     }\r
365 \r
366     //-------------------------------------------------------------------------\r
367     // Assorted calculation utilities\r
368     //\r
369 \r
370 // Unused code - Alan 2003-05\r
371 //    /**\r
372 //     * Find the day of the week for a given day\r
373 //     *\r
374 //     * @param day   The # of days since the start of the Islamic calendar.\r
375 //     */\r
376 //    // private and uncalled, perhaps not used yet?\r
377 //    private static final int absoluteDayToDayOfWeek(long day)\r
378 //    {\r
379 //        // Calculate the day of the week.\r
380 //        // This relies on the fact that the epoch was a Thursday.\r
381 //        int dayOfWeek = (int)(day + THURSDAY) % 7 + SUNDAY;\r
382 //        if (dayOfWeek < 0) {\r
383 //            dayOfWeek += 7;\r
384 //        }\r
385 //        return dayOfWeek;\r
386 //    }\r
387 \r
388     /**\r
389      * Determine whether a year is a leap year in the Islamic civil calendar\r
390      */\r
391     private final static boolean civilLeapYear(int year)\r
392     {\r
393         return (14 + 11 * year) % 30 < 11;\r
394         \r
395     }\r
396     \r
397     /**\r
398      * Return the day # on which the given year starts.  Days are counted\r
399      * from the Hijri epoch, origin 0.\r
400      */\r
401     private long yearStart(int year) {\r
402         if (civil) {\r
403             return (year-1)*354 + (long)Math.floor((3+11*year)/30.0);\r
404         } else {\r
405             return trueMonthStart(12*(year-1));\r
406         }\r
407     }\r
408     \r
409     /**\r
410      * Return the day # on which the given month starts.  Days are counted\r
411      * from the Hijri epoch, origin 0.\r
412      *\r
413      * @param year  The hijri year\r
414      * @param month  The hijri month, 0-based\r
415      */\r
416     private long monthStart(int year, int month) {\r
417         if (civil) {\r
418             return (long)Math.ceil(29.5*month)\r
419                     + (year-1)*354 + (long)Math.floor((3+11*year)/30.0);\r
420         } else {\r
421             return trueMonthStart(12*(year-1) + month);\r
422         }\r
423     }\r
424     \r
425     /**\r
426      * Find the day number on which a particular month of the true/lunar\r
427      * Islamic calendar starts.\r
428      *\r
429      * @param month The month in question, origin 0 from the Hijri epoch\r
430      *\r
431      * @return The day number on which the given month starts.\r
432      */\r
433     private static final long trueMonthStart(long month)\r
434     {\r
435         long start = cache.get(month);\r
436 \r
437         if (start == CalendarCache.EMPTY)\r
438         {\r
439             // Make a guess at when the month started, using the average length\r
440             long origin = HIJRA_MILLIS \r
441                         + (long)Math.floor(month * CalendarAstronomer.SYNODIC_MONTH) * ONE_DAY;\r
442 \r
443             double age = moonAge(origin);\r
444 \r
445             if (moonAge(origin) >= 0) {\r
446                 // The month has already started\r
447                 do {\r
448                     origin -= ONE_DAY;\r
449                     age = moonAge(origin);\r
450                 } while (age >= 0);\r
451             }\r
452             else {\r
453                 // Preceding month has not ended yet.\r
454                 do {\r
455                     origin += ONE_DAY;\r
456                     age = moonAge(origin);\r
457                 } while (age < 0);\r
458             }\r
459 \r
460             start = (origin - HIJRA_MILLIS) / ONE_DAY + 1;\r
461             \r
462             cache.put(month, start);\r
463         }\r
464         return start;\r
465     }\r
466 \r
467     /**\r
468      * Return the "age" of the moon at the given time; this is the difference\r
469      * in ecliptic latitude between the moon and the sun.  This method simply\r
470      * calls CalendarAstronomer.moonAge, converts to degrees, \r
471      * and adjusts the resultto be in the range [-180, 180].\r
472      *\r
473      * @param time  The time at which the moon's age is desired,\r
474      *              in millis since 1/1/1970.\r
475      */\r
476     static final double moonAge(long time)\r
477     {\r
478         double age = 0;\r
479         \r
480         synchronized(astro) {\r
481             astro.setTime(time);\r
482             age = astro.getMoonAge();\r
483         }\r
484         // Convert to degrees and normalize...\r
485         age = age * 180 / Math.PI;\r
486         if (age > 180) {\r
487             age = age - 360;\r
488         }\r
489 \r
490         return age;\r
491     }\r
492 \r
493     //-------------------------------------------------------------------------\r
494     // Internal data....\r
495     //\r
496     \r
497     // And an Astronomer object for the moon age calculations\r
498     private static CalendarAstronomer astro = new CalendarAstronomer();\r
499     \r
500     private static CalendarCache cache = new CalendarCache();\r
501     \r
502     /**\r
503      * <code>true</code> if this object uses the fixed-cycle Islamic civil calendar,\r
504      * and <code>false</code> if it approximates the true religious calendar using\r
505      * astronomical calculations for the time of the new moon.\r
506      *\r
507      * @serial\r
508      */\r
509     private boolean civil = true;\r
510 \r
511     //----------------------------------------------------------------------\r
512     // Calendar framework\r
513     //----------------------------------------------------------------------\r
514 \r
515     /**\r
516      * Return the length (in days) of the given month.\r
517      *\r
518      * @param extendedYear  The hijri year\r
519      * @param month The hijri month, 0-based\r
520      * @stable ICU 2.8\r
521      */\r
522     protected int handleGetMonthLength(int extendedYear, int month) {\r
523 \r
524         int length = 0;\r
525         \r
526         if (civil) {\r
527             length = 29 + (month+1) % 2;\r
528             if (month == DHU_AL_HIJJAH && civilLeapYear(extendedYear)) {\r
529                 length++;\r
530             }\r
531         } else {\r
532             month = 12*(extendedYear-1) + month;\r
533             length = (int)( trueMonthStart(month+1) - trueMonthStart(month) );\r
534         }\r
535         return length;\r
536     }\r
537 \r
538     /**\r
539      * Return the number of days in the given Islamic year\r
540      * @stable ICU 2.8\r
541      */\r
542     protected int handleGetYearLength(int extendedYear) {\r
543         if (civil) {\r
544             return 354 + (civilLeapYear(extendedYear) ? 1 : 0);\r
545         } else {\r
546             int month = 12*(extendedYear-1);\r
547             return (int)(trueMonthStart(month + 12) - trueMonthStart(month));\r
548         }\r
549     }\r
550     \r
551     //-------------------------------------------------------------------------\r
552     // Functions for converting from field values to milliseconds....\r
553     //-------------------------------------------------------------------------\r
554 \r
555     // Return JD of start of given month/year\r
556     /**\r
557      * @stable ICU 2.8\r
558      */\r
559     protected int handleComputeMonthStart(int eyear, int month, boolean useMonth) {\r
560         return (int) monthStart(eyear, month) + 1948439;\r
561     }    \r
562 \r
563     //-------------------------------------------------------------------------\r
564     // Functions for converting from milliseconds to field values\r
565     //-------------------------------------------------------------------------\r
566 \r
567     /**\r
568      * @stable ICU 2.8\r
569      */\r
570     protected int handleGetExtendedYear() {\r
571         int year;\r
572         if (newerField(EXTENDED_YEAR, YEAR) == EXTENDED_YEAR) {\r
573             year = internalGet(EXTENDED_YEAR, 1); // Default to year 1\r
574         } else {\r
575             year = internalGet(YEAR, 1); // Default to year 1\r
576         }\r
577         return year;\r
578     }\r
579 \r
580     /**\r
581      * Override Calendar to compute several fields specific to the Islamic\r
582      * calendar system.  These are:\r
583      *\r
584      * <ul><li>ERA\r
585      * <li>YEAR\r
586      * <li>MONTH\r
587      * <li>DAY_OF_MONTH\r
588      * <li>DAY_OF_YEAR\r
589      * <li>EXTENDED_YEAR</ul>\r
590      * \r
591      * The DAY_OF_WEEK and DOW_LOCAL fields are already set when this\r
592      * method is called. The getGregorianXxx() methods return Gregorian\r
593      * calendar equivalents for the given Julian day.\r
594      * @stable ICU 2.8\r
595      */\r
596     protected void handleComputeFields(int julianDay) {\r
597         int year, month, dayOfMonth, dayOfYear;\r
598         long monthStart;\r
599         long days = julianDay - 1948440;\r
600 \r
601         if (civil) {\r
602             // Use the civil calendar approximation, which is just arithmetic\r
603             year  = (int)Math.floor( (30 * days + 10646) / 10631.0 );\r
604             month = (int)Math.ceil((days - 29 - yearStart(year)) / 29.5 );\r
605             month = Math.min(month, 11);\r
606             monthStart = monthStart(year, month);\r
607         } else {\r
608             // Guess at the number of elapsed full months since the epoch\r
609             int months = (int)Math.floor(days / CalendarAstronomer.SYNODIC_MONTH);\r
610 \r
611             monthStart = (long)Math.floor(months * CalendarAstronomer.SYNODIC_MONTH - 1);\r
612 \r
613             if ( days - monthStart >= 25 && moonAge(internalGetTimeInMillis()) > 0) {\r
614                 // If we're near the end of the month, assume next month and search backwards\r
615                 months++;\r
616             }\r
617 \r
618             // Find out the last time that the new moon was actually visible at this longitude\r
619             // This returns midnight the night that the moon was visible at sunset.\r
620             while ((monthStart = trueMonthStart(months)) > days) {\r
621                 // If it was after the date in question, back up a month and try again\r
622                 months--;\r
623             }\r
624 \r
625             year = months / 12 + 1;\r
626             month = months % 12;\r
627         }\r
628 \r
629         dayOfMonth = (int)(days - monthStart(year, month)) + 1;\r
630 \r
631         // Now figure out the day of the year.\r
632         dayOfYear = (int)(days - monthStart(year, 0) + 1);\r
633 \r
634         internalSet(ERA, 0);\r
635         internalSet(YEAR, year);\r
636         internalSet(EXTENDED_YEAR, year);\r
637         internalSet(MONTH, month);\r
638         internalSet(DAY_OF_MONTH, dayOfMonth);\r
639         internalSet(DAY_OF_YEAR, dayOfYear);       \r
640     }    \r
641 \r
642     /**\r
643      * {@inheritDoc}\r
644      * @stable ICU 3.8\r
645      */\r
646     public String getType() {\r
647         return "islamic";\r
648     }\r
649 \r
650     /*\r
651     private static CalendarFactory factory;\r
652     public static CalendarFactory factory() {\r
653         if (factory == null) {\r
654             factory = new CalendarFactory() {\r
655                 public Calendar create(TimeZone tz, ULocale loc) {\r
656                     return new IslamicCalendar(tz, loc);\r
657                 }\r
658 \r
659                 public String factoryName() {\r
660                     return "Islamic";\r
661                 }\r
662             };\r
663         }\r
664         return factory;\r
665     }\r
666     */\r
667 }\r