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 override; 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 override; 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 override; 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 override; 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 override; 321 322 //------------------------------------------------------------------------- 323 // Functions for converting from milliseconds to field values 324 //------------------------------------------------------------------------- 325 326 /** 327 * @internal 328 */ 329 virtual int32_t handleGetExtendedYear() override; 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) override; 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 override; 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 override; 378 379 private: 380 IslamicCalendar() = delete; // 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 override; 395 396 397 /** 398 * Returns true because the Islamic Calendar does have a default century 399 * @internal 400 */ 401 virtual UBool haveDefaultCentury() const override; 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 override; 409 410 /** 411 * Returns the year in which the default century begins 412 * @internal 413 */ 414 virtual int32_t defaultCenturyStartYear() const override; 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