1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4  ********************************************************************************
5  * Copyright (C) 2003-2013, International Business Machines Corporation
6  * and others. All Rights Reserved.
7  ******************************************************************************
8  *
9  * File ISLAMCAL.H
10  *
11  * Modification History:
12  *
13  *   Date        Name        Description
14  *   10/14/2003  srl         ported from java IslamicCalendar
15  *****************************************************************************
16  */
17 
18 #ifndef ISLAMCAL_H
19 #define ISLAMCAL_H
20 
21 #include "unicode/utypes.h"
22 
23 #if !UCONFIG_NO_FORMATTING
24 
25 #include "unicode/calendar.h"
26 
27 U_NAMESPACE_BEGIN
28 
29 /**
30  * <code>IslamicCalendar</code> is a subclass of <code>Calendar</code>
31  * that implements the Islamic civil and religious calendars.  It
32  * is used as the civil calendar in most of the Arab world and the
33  * liturgical calendar of the Islamic faith worldwide.  This calendar
34  * is also known as the "Hijri" calendar, since it starts at the time
35  * of Mohammed's emigration (or "hijra") to Medinah on Thursday,
36  * July 15, 622 AD (Julian).
37  * <p>
38  * The Islamic calendar is strictly lunar, and thus an Islamic year of twelve
39  * lunar months does not correspond to the solar year used by most other
40  * calendar systems, including the Gregorian.  An Islamic year is, on average,
41  * about 354 days long, so each successive Islamic year starts about 11 days
42  * earlier in the corresponding Gregorian year.
43  * <p>
44  * Each month of the calendar starts when the new moon's crescent is visible
45  * at sunset.  However, in order to keep the time fields in this class
46  * synchronized with those of the other calendars and with local clock time,
47  * we treat days and months as beginning at midnight,
48  * roughly 6 hours after the corresponding sunset.
49  * <p>
50  * There are two main variants of the Islamic calendar in existence.  The first
51  * is the <em>civil</em> calendar, which uses a fixed cycle of alternating 29-
52  * and 30-day months, with a leap day added to the last month of 11 out of
53  * every 30 years.  This calendar is easily calculated and thus predictable in
54  * advance, so it is used as the civil calendar in a number of Arab countries.
55  * This is the default behavior of a newly-created <code>IslamicCalendar</code>
56  * object.
57  * <p>
58  * The Islamic <em>religious</em> calendar, however, is based on the <em>observation</em>
59  * of the crescent moon.  It is thus affected by the position at which the
60  * observations are made, seasonal variations in the time of sunset, the
61  * eccentricities of the moon's orbit, and even the weather at the observation
62  * site.  This makes it impossible to calculate in advance, and it causes the
63  * start of a month in the religious calendar to differ from the civil calendar
64  * by up to three days.
65  * <p>
66  * Using astronomical calculations for the position of the sun and moon, the
67  * moon's illumination, and other factors, it is possible to determine the start
68  * of a lunar month with a fairly high degree of certainty.  However, these
69  * calculations are extremely complicated and thus slow, so most algorithms,
70  * including the one used here, are only approximations of the true astronomical
71  * calculations.  At present, the approximations used in this class are fairly
72  * simplistic; they will be improved in later versions of the code.
73  * <p>
74  * The {@link #setCivil setCivil} method determines
75  * which approach is used to determine the start of a month.  By default, the
76  * fixed-cycle civil calendar is used.  However, if <code>setCivil(false)</code>
77  * is called, an approximation of the true lunar calendar will be used.
78  *
79  * @see GregorianCalendar
80  *
81  * @author Laura Werner
82  * @author Alan Liu
83  * @author Steven R. Loomis
84  * @internal
85  */
86 class U_I18N_API IslamicCalendar : public Calendar {
87  public:
88   //-------------------------------------------------------------------------
89   // Constants...
90   //-------------------------------------------------------------------------
91 
92   /**
93    * Calendar type - civil or religious or um alqura
94    * @internal
95    */
96   enum ECalculationType {
97     ASTRONOMICAL,
98     CIVIL,
99     UMALQURA,
100     TBLA
101   };
102 
103   /**
104    * Constants for the months
105    * @internal
106    */
107   enum EMonths {
108     /**
109      * Constant for Muharram, the 1st month of the Islamic year.
110      * @internal
111      */
112     MUHARRAM = 0,
113 
114     /**
115      * Constant for Safar, the 2nd month of the Islamic year.
116      * @internal
117      */
118     SAFAR = 1,
119 
120     /**
121      * Constant for Rabi' al-awwal (or Rabi' I), the 3rd month of the Islamic year.
122      * @internal
123      */
124     RABI_1 = 2,
125 
126     /**
127      * Constant for Rabi' al-thani or (Rabi' II), the 4th month of the Islamic year.
128      * @internal
129      */
130     RABI_2 = 3,
131 
132     /**
133      * Constant for Jumada al-awwal or (Jumada I), the 5th month of the Islamic year.
134      * @internal
135      */
136     JUMADA_1 = 4,
137 
138     /**
139      * Constant for Jumada al-thani or (Jumada II), the 6th month of the Islamic year.
140      * @internal
141      */
142     JUMADA_2 = 5,
143 
144     /**
145      * Constant for Rajab, the 7th month of the Islamic year.
146      * @internal
147      */
148     RAJAB = 6,
149 
150     /**
151      * Constant for Sha'ban, the 8th month of the Islamic year.
152      * @internal
153      */
154     SHABAN = 7,
155 
156     /**
157      * Constant for Ramadan, the 9th month of the Islamic year.
158      * @internal
159      */
160     RAMADAN = 8,
161 
162     /**
163      * Constant for Shawwal, the 10th month of the Islamic year.
164      * @internal
165      */
166     SHAWWAL = 9,
167 
168     /**
169      * Constant for Dhu al-Qi'dah, the 11th month of the Islamic year.
170      * @internal
171      */
172     DHU_AL_QIDAH = 10,
173 
174     /**
175      * Constant for Dhu al-Hijjah, the 12th month of the Islamic year.
176      * @internal
177      */
178     DHU_AL_HIJJAH = 11,
179 
180     ISLAMIC_MONTH_MAX
181   };
182 
183 
184   //-------------------------------------------------------------------------
185   // Constructors...
186   //-------------------------------------------------------------------------
187 
188   /**
189    * Constructs an IslamicCalendar based on the current time in the default time zone
190    * with the given locale.
191    *
192    * @param aLocale  The given locale.
193    * @param success  Indicates the status of IslamicCalendar object construction.
194    *                 Returns U_ZERO_ERROR if constructed successfully.
195    * @param type     The Islamic calendar calculation type. The default value is CIVIL.
196    * @internal
197    */
198   IslamicCalendar(const Locale& aLocale, UErrorCode &success, ECalculationType type = CIVIL);
199 
200   /**
201    * Copy Constructor
202    * @internal
203    */
204   IslamicCalendar(const IslamicCalendar& other);
205 
206   /**
207    * Destructor.
208    * @internal
209    */
210   virtual ~IslamicCalendar();
211 
212   /**
213    * Sets Islamic calendar calculation type used by this instance.
214    *
215    * @param type    The calendar calculation type, <code>CIVIL</code> to use the civil
216    *                calendar, <code>ASTRONOMICAL</code> to use the astronomical calendar.
217    * @internal
218    */
219   void setCalculationType(ECalculationType type, UErrorCode &status);
220 
221   /**
222    * Returns <code>true</code> if this object is using the fixed-cycle civil
223    * calendar, or <code>false</code> if using the religious, astronomical
224    * calendar.
225    * @internal
226    */
227   UBool isCivil();
228 
229 
230   // TODO: copy c'tor, etc
231 
232   // clone
233   virtual IslamicCalendar* clone() const;
234 
235  private:
236   /**
237    * Determine whether a year is a leap year in the Islamic civil calendar
238    */
239   static UBool civilLeapYear(int32_t year);
240 
241   /**
242    * Return the day # on which the given year starts.  Days are counted
243    * from the Hijri epoch, origin 0.
244    */
245   int32_t yearStart(int32_t year) const;
246 
247   /**
248    * Return the day # on which the given month starts.  Days are counted
249    * from the Hijri epoch, origin 0.
250    *
251    * @param year  The hijri year
252    * @param year  The hijri month, 0-based
253    */
254   int32_t monthStart(int32_t year, int32_t month) const;
255 
256   /**
257    * Find the day number on which a particular month of the true/lunar
258    * Islamic calendar starts.
259    *
260    * @param month The month in question, origin 0 from the Hijri epoch
261    *
262    * @return The day number on which the given month starts.
263    */
264   int32_t trueMonthStart(int32_t month) const;
265 
266   /**
267    * Return the "age" of the moon at the given time; this is the difference
268    * in ecliptic latitude between the moon and the sun.  This method simply
269    * calls CalendarAstronomer.moonAge, converts to degrees,
270    * and adjusts the resultto be in the range [-180, 180].
271    *
272    * @param time  The time at which the moon's age is desired,
273    *              in millis since 1/1/1970.
274    */
275   static double moonAge(UDate time, UErrorCode &status);
276 
277   //-------------------------------------------------------------------------
278   // Internal data....
279   //
280 
281   /**
282    * <code>CIVIL</code> if this object uses the fixed-cycle Islamic civil calendar,
283    * and <code>ASTRONOMICAL</code> if it approximates the true religious calendar using
284    * astronomical calculations for the time of the new moon.
285    */
286   ECalculationType cType;
287 
288   //----------------------------------------------------------------------
289   // Calendar framework
290   //----------------------------------------------------------------------
291  protected:
292   /**
293    * @internal
294    */
295   virtual int32_t handleGetLimit(UCalendarDateFields field, ELimitType limitType) const;
296 
297   /**
298    * Return the length (in days) of the given month.
299    *
300    * @param year  The hijri year
301    * @param year  The hijri month, 0-based
302    * @internal
303    */
304   virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month) const;
305 
306   /**
307    * Return the number of days in the given Islamic year
308    * @internal
309    */
310   virtual int32_t handleGetYearLength(int32_t extendedYear) const;
311 
312   //-------------------------------------------------------------------------
313   // Functions for converting from field values to milliseconds....
314   //-------------------------------------------------------------------------
315 
316   // Return JD of start of given month/year
317   /**
318    * @internal
319    */
320   virtual int32_t handleComputeMonthStart(int32_t eyear, int32_t month, UBool useMonth) const;
321 
322   //-------------------------------------------------------------------------
323   // Functions for converting from milliseconds to field values
324   //-------------------------------------------------------------------------
325 
326   /**
327    * @internal
328    */
329   virtual int32_t handleGetExtendedYear();
330 
331   /**
332    * Override Calendar to compute several fields specific to the Islamic
333    * calendar system.  These are:
334    *
335    * <ul><li>ERA
336    * <li>YEAR
337    * <li>MONTH
338    * <li>DAY_OF_MONTH
339    * <li>DAY_OF_YEAR
340    * <li>EXTENDED_YEAR</ul>
341    *
342    * The DAY_OF_WEEK and DOW_LOCAL fields are already set when this
343    * method is called. The getGregorianXxx() methods return Gregorian
344    * calendar equivalents for the given Julian day.
345    * @internal
346    */
347   virtual void handleComputeFields(int32_t julianDay, UErrorCode &status);
348 
349   // UObject stuff
350  public:
351   /**
352    * @return   The class ID for this object. All objects of a given class have the
353    *           same class ID. Objects of other classes have different class IDs.
354    * @internal
355    */
356   virtual UClassID getDynamicClassID(void) const;
357 
358   /**
359    * Return the class ID for this class. This is useful only for comparing to a return
360    * value from getDynamicClassID(). For example:
361    *
362    *      Base* polymorphic_pointer = createPolymorphicObject();
363    *      if (polymorphic_pointer->getDynamicClassID() ==
364    *          Derived::getStaticClassID()) ...
365    *
366    * @return   The class ID for all objects of this class.
367    * @internal
368    */
369   /*U_I18N_API*/ static UClassID U_EXPORT2 getStaticClassID(void);
370 
371   /**
372    * return the calendar type, "buddhist".
373    *
374    * @return calendar type
375    * @internal
376    */
377   virtual const char * getType() const;
378 
379  private:
380   IslamicCalendar(); // default constructor not implemented
381 
382   // Default century.
383  protected:
384 
385   /**
386    * (Overrides Calendar) Return true if the current date for this Calendar is in
387    * Daylight Savings Time. Recognizes DST_OFFSET, if it is set.
388    *
389    * @param status Fill-in parameter which receives the status of this operation.
390    * @return   True if the current date for this Calendar is in Daylight Savings Time,
391    *           false, otherwise.
392    * @internal
393    */
394   virtual UBool inDaylightTime(UErrorCode& status) const;
395 
396 
397   /**
398    * Returns true because the Islamic Calendar does have a default century
399    * @internal
400    */
401   virtual UBool haveDefaultCentury() const;
402 
403   /**
404    * Returns the date of the start of the default century
405    * @return start of century - in milliseconds since epoch, 1970
406    * @internal
407    */
408   virtual UDate defaultCenturyStart() const;
409 
410   /**
411    * Returns the year in which the default century begins
412    * @internal
413    */
414   virtual int32_t defaultCenturyStartYear() const;
415 
416  private:
417   /**
418    * Initializes the 100-year window that dates with 2-digit years
419    * are considered to fall within so that its start date is 80 years
420    * before the current time.
421    */
422   static void U_CALLCONV initializeSystemDefaultCentury(void);
423 };
424 
425 U_NAMESPACE_END
426 
427 #endif
428 #endif
429 
430 
431 
432