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. This calendar variant is implemented in the IslamicCivilCalendar 57 * class. 58 * <p> 59 * The Islamic <em>religious</em> calendar, however, is based on the <em>observation</em> 60 * of the crescent moon. It is thus affected by the position at which the 61 * observations are made, seasonal variations in the time of sunset, the 62 * eccentricities of the moon's orbit, and even the weather at the observation 63 * site. This makes it impossible to calculate in advance, and it causes the 64 * start of a month in the religious calendar to differ from the civil calendar 65 * by up to three days. 66 * <p> 67 * Using astronomical calculations for the position of the sun and moon, the 68 * moon's illumination, and other factors, it is possible to determine the start 69 * of a lunar month with a fairly high degree of certainty. However, these 70 * calculations are extremely complicated and thus slow, so most algorithms, 71 * including the one used here, are only approximations of the true astronomical 72 * calculations. At present, the approximations used in this class are fairly 73 * simplistic; they will be improved in later versions of the code. 74 * <p> 75 * 76 * @see GregorianCalendar 77 * 78 * @author Laura Werner 79 * @author Alan Liu 80 * @author Steven R. Loomis 81 * @internal 82 */ 83 class U_I18N_API IslamicCalendar : public Calendar { 84 public: 85 //------------------------------------------------------------------------- 86 // Constants... 87 //------------------------------------------------------------------------- 88 /** 89 * Constants for the months 90 * @internal 91 */ 92 enum EMonths { 93 /** 94 * Constant for Muharram, the 1st month of the Islamic year. 95 * @internal 96 */ 97 MUHARRAM = 0, 98 99 /** 100 * Constant for Safar, the 2nd month of the Islamic year. 101 * @internal 102 */ 103 SAFAR = 1, 104 105 /** 106 * Constant for Rabi' al-awwal (or Rabi' I), the 3rd month of the Islamic year. 107 * @internal 108 */ 109 RABI_1 = 2, 110 111 /** 112 * Constant for Rabi' al-thani or (Rabi' II), the 4th month of the Islamic year. 113 * @internal 114 */ 115 RABI_2 = 3, 116 117 /** 118 * Constant for Jumada al-awwal or (Jumada I), the 5th month of the Islamic year. 119 * @internal 120 */ 121 JUMADA_1 = 4, 122 123 /** 124 * Constant for Jumada al-thani or (Jumada II), the 6th month of the Islamic year. 125 * @internal 126 */ 127 JUMADA_2 = 5, 128 129 /** 130 * Constant for Rajab, the 7th month of the Islamic year. 131 * @internal 132 */ 133 RAJAB = 6, 134 135 /** 136 * Constant for Sha'ban, the 8th month of the Islamic year. 137 * @internal 138 */ 139 SHABAN = 7, 140 141 /** 142 * Constant for Ramadan, the 9th month of the Islamic year. 143 * @internal 144 */ 145 RAMADAN = 8, 146 147 /** 148 * Constant for Shawwal, the 10th month of the Islamic year. 149 * @internal 150 */ 151 SHAWWAL = 9, 152 153 /** 154 * Constant for Dhu al-Qi'dah, the 11th month of the Islamic year. 155 * @internal 156 */ 157 DHU_AL_QIDAH = 10, 158 159 /** 160 * Constant for Dhu al-Hijjah, the 12th month of the Islamic year. 161 * @internal 162 */ 163 DHU_AL_HIJJAH = 11, 164 165 ISLAMIC_MONTH_MAX 166 }; 167 168 169 //------------------------------------------------------------------------- 170 // Constructors... 171 //------------------------------------------------------------------------- 172 173 /** 174 * Constructs an IslamicCalendar based on the current time in the default time zone 175 * with the given locale. 176 * 177 * @param aLocale The given locale. 178 * @param success Indicates the status of IslamicCalendar object construction. 179 * Returns U_ZERO_ERROR if constructed successfully. 180 * @internal 181 */ 182 IslamicCalendar(const Locale& aLocale, UErrorCode &success); 183 184 /** 185 * Copy Constructor 186 * @internal 187 */ 188 IslamicCalendar(const IslamicCalendar& other) = default; 189 190 /** 191 * Destructor. 192 * @internal 193 */ 194 virtual ~IslamicCalendar(); 195 196 // clone 197 virtual IslamicCalendar* clone() const override; 198 199 protected: 200 /** 201 * Determine whether a year is a leap year in the Islamic civil calendar 202 */ 203 static UBool civilLeapYear(int32_t year); 204 205 /** 206 * Return the day # on which the given year starts. Days are counted 207 * from the Hijri epoch, origin 0. 208 */ 209 virtual int32_t yearStart(int32_t year) const; 210 211 /** 212 * Return the day # on which the given month starts. Days are counted 213 * from the Hijri epoch, origin 0. 214 * 215 * @param year The hijri year 216 * @param year The hijri month, 0-based 217 */ 218 virtual int32_t monthStart(int32_t year, int32_t month) const; 219 220 /** 221 * Find the day number on which a particular month of the true/lunar 222 * Islamic calendar starts. 223 * 224 * @param month The month in question, origin 0 from the Hijri epoch 225 * 226 * @return The day number on which the given month starts. 227 */ 228 int32_t trueMonthStart(int32_t month) const; 229 230 private: 231 /** 232 * Return the "age" of the moon at the given time; this is the difference 233 * in ecliptic latitude between the moon and the sun. This method simply 234 * calls CalendarAstronomer.moonAge, converts to degrees, 235 * and adjusts the resultto be in the range [-180, 180]. 236 * 237 * @param time The time at which the moon's age is desired, 238 * in millis since 1/1/1970. 239 */ 240 static double moonAge(UDate time, UErrorCode &status); 241 242 //---------------------------------------------------------------------- 243 // Calendar framework 244 //---------------------------------------------------------------------- 245 protected: 246 /** 247 * @internal 248 */ 249 virtual int32_t handleGetLimit(UCalendarDateFields field, ELimitType limitType) const override; 250 251 /** 252 * Return the length (in days) of the given month. 253 * 254 * @param year The hijri year 255 * @param year The hijri month, 0-based 256 * @internal 257 */ 258 virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month) const override; 259 260 /** 261 * Return the number of days in the given Islamic year 262 * @internal 263 */ 264 virtual int32_t handleGetYearLength(int32_t extendedYear) const override; 265 266 //------------------------------------------------------------------------- 267 // Functions for converting from field values to milliseconds.... 268 //------------------------------------------------------------------------- 269 270 // Return JD of start of given month/year 271 /** 272 * @internal 273 */ 274 virtual int32_t handleComputeMonthStart(int32_t eyear, int32_t month, UBool useMonth) const override; 275 276 //------------------------------------------------------------------------- 277 // Functions for converting from milliseconds to field values 278 //------------------------------------------------------------------------- 279 280 /** 281 * @internal 282 */ 283 virtual int32_t handleGetExtendedYear() override; 284 285 /** 286 * Override Calendar to compute several fields specific to the Islamic 287 * calendar system. These are: 288 * 289 * <ul><li>ERA 290 * <li>YEAR 291 * <li>MONTH 292 * <li>DAY_OF_MONTH 293 * <li>DAY_OF_YEAR 294 * <li>EXTENDED_YEAR</ul> 295 * 296 * The DAY_OF_WEEK and DOW_LOCAL fields are already set when this 297 * method is called. The getGregorianXxx() methods return Gregorian 298 * calendar equivalents for the given Julian day. 299 * @internal 300 */ 301 virtual void handleComputeFields(int32_t julianDay, UErrorCode &status) override; 302 303 /** 304 * Return the epoc. 305 * @internal 306 */ 307 virtual int32_t getEpoc() const; 308 309 // UObject stuff 310 public: 311 /** 312 * @return The class ID for this object. All objects of a given class have the 313 * same class ID. Objects of other classes have different class IDs. 314 * @internal 315 */ 316 virtual UClassID getDynamicClassID() const override; 317 318 /** 319 * Return the class ID for this class. This is useful only for comparing to a return 320 * value from getDynamicClassID(). For example: 321 * 322 * Base* polymorphic_pointer = createPolymorphicObject(); 323 * if (polymorphic_pointer->getDynamicClassID() == 324 * Derived::getStaticClassID()) ... 325 * 326 * @return The class ID for all objects of this class. 327 * @internal 328 */ 329 /*U_I18N_API*/ static UClassID U_EXPORT2 getStaticClassID(); 330 331 /** 332 * return the calendar type, "islamic". 333 * 334 * @return calendar type 335 * @internal 336 */ 337 virtual const char * getType() const override; 338 339 /** 340 * @return The related Gregorian year; will be obtained by modifying the value 341 * obtained by get from UCAL_EXTENDED_YEAR field 342 * @internal 343 */ 344 virtual int32_t getRelatedYear(UErrorCode &status) const override; 345 346 /** 347 * @param year The related Gregorian year to set; will be modified as necessary then 348 * set in UCAL_EXTENDED_YEAR field 349 * @internal 350 */ 351 virtual void setRelatedYear(int32_t year) override; 352 353 /** 354 * Returns true if the date is in a leap year. 355 * 356 * @param status ICU Error Code 357 * @return True if the date in the fields is in a Temporal proposal 358 * defined leap year. False otherwise. 359 */ 360 virtual bool inTemporalLeapYear(UErrorCode &status) const override; 361 362 private: 363 IslamicCalendar() = delete; // default constructor not implemented 364 365 // Default century. 366 protected: 367 /** 368 * Returns true because the Islamic Calendar does have a default century 369 * @internal 370 */ 371 virtual UBool haveDefaultCentury() const override; 372 373 /** 374 * Returns the date of the start of the default century 375 * @return start of century - in milliseconds since epoch, 1970 376 * @internal 377 */ 378 virtual UDate defaultCenturyStart() const override; 379 380 /** 381 * Returns the year in which the default century begins 382 * @internal 383 */ 384 virtual int32_t defaultCenturyStartYear() const override; 385 386 private: 387 /** 388 * Initializes the 100-year window that dates with 2-digit years 389 * are considered to fall within so that its start date is 80 years 390 * before the current time. 391 */ 392 static void U_CALLCONV initializeSystemDefaultCentury(); 393 }; 394 395 /* 396 * IslamicCivilCalendar is one of the two main variants of the Islamic calendar. 397 * The <em>civil</em> calendar, which uses a fixed cycle of alternating 29- 398 * and 30-day months, with a leap day added to the last month of 11 out of 399 * every 30 years. This calendar is easily calculated and thus predictable in 400 * advance, so it is used as the civil calendar in a number of Arab countries. 401 * This calendar is referring as "Islamic calendar, tabular (intercalary years 402 * [2,5,7,10,13,16,18,21,24,26,29]- civil epoch" in CLDR. 403 */ 404 class U_I18N_API IslamicCivilCalendar : public IslamicCalendar { 405 public: 406 /** 407 * Constructs an IslamicCivilCalendar based on the current time in the default time zone 408 * with the given locale. 409 * 410 * @param aLocale The given locale. 411 * @param success Indicates the status of IslamicCivilCalendar object construction. 412 * Returns U_ZERO_ERROR if constructed successfully. 413 * @internal 414 */ 415 IslamicCivilCalendar(const Locale& aLocale, UErrorCode &success); 416 417 /** 418 * Copy Constructor 419 * @internal 420 */ 421 IslamicCivilCalendar(const IslamicCivilCalendar& other) = default; 422 423 /** 424 * Destructor. 425 * @internal 426 */ 427 virtual ~IslamicCivilCalendar(); 428 429 // clone 430 virtual IslamicCivilCalendar* clone() const override; 431 432 /** 433 * @return The class ID for this object. All objects of a given class have the 434 * same class ID. Objects of other classes have different class IDs. 435 * @internal 436 */ 437 virtual UClassID getDynamicClassID() const override; 438 439 /** 440 * Return the class ID for this class. This is useful only for comparing to a return 441 * value from getDynamicClassID(). For example: 442 * 443 * Base* polymorphic_pointer = createPolymorphicObject(); 444 * if (polymorphic_pointer->getDynamicClassID() == 445 * Derived::getStaticClassID()) ... 446 * 447 * @return The class ID for all objects of this class. 448 * @internal 449 */ 450 static UClassID U_EXPORT2 getStaticClassID(); 451 452 /** 453 * return the calendar type, "islamic-civil". 454 * 455 * @return calendar type 456 * @internal 457 */ 458 virtual const char * getType() const override; 459 460 protected: 461 /** 462 * Return the day # on which the given year starts. Days are counted 463 * from the Hijri epoch, origin 0. 464 * @internal 465 */ 466 virtual int32_t yearStart(int32_t year) const override; 467 468 /** 469 * Return the day # on which the given month starts. Days are counted 470 * from the Hijri epoch, origin 0. 471 * 472 * @param year The hijri year 473 * @param year The hijri month, 0-based 474 * @internal 475 */ 476 virtual int32_t monthStart(int32_t year, int32_t month) const override; 477 478 /** 479 * Return the length (in days) of the given month. 480 * 481 * @param year The hijri year 482 * @param year The hijri month, 0-based 483 * @internal 484 */ 485 virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month) const override; 486 487 /** 488 * Return the number of days in the given Islamic year 489 * @internal 490 */ 491 virtual int32_t handleGetYearLength(int32_t extendedYear) const override; 492 493 /** 494 * Override Calendar to compute several fields specific to the Islamic 495 * calendar system. These are: 496 * 497 * <ul><li>ERA 498 * <li>YEAR 499 * <li>MONTH 500 * <li>DAY_OF_MONTH 501 * <li>DAY_OF_YEAR 502 * <li>EXTENDED_YEAR</ul> 503 * 504 * The DAY_OF_WEEK and DOW_LOCAL fields are already set when this 505 * method is called. The getGregorianXxx() methods return Gregorian 506 * calendar equivalents for the given Julian day. 507 * @internal 508 */ 509 virtual void handleComputeFields(int32_t julianDay, UErrorCode &status) override; 510 }; 511 512 /* 513 * IslamicTBLACalendar calendar. 514 * This is a subclass of IslamicCivilCalendar. The only differences in the 515 * calendar math is it uses different epoch. 516 * This calendar is referring as "Islamic calendar, tabular (intercalary years 517 * [2,5,7,10,13,16,18,21,24,26,29] - astronomical epoch" in CLDR. 518 */ 519 class U_I18N_API IslamicTBLACalendar : public IslamicCivilCalendar { 520 public: 521 /** 522 * Constructs an IslamicTBLACalendar based on the current time in the default time zone 523 * with the given locale. 524 * 525 * @param aLocale The given locale. 526 * @param success Indicates the status of IslamicTBLACalendar object construction. 527 * Returns U_ZERO_ERROR if constructed successfully. 528 * @internal 529 */ 530 IslamicTBLACalendar(const Locale& aLocale, UErrorCode &success); 531 532 /** 533 * Copy Constructor 534 * @internal 535 */ 536 IslamicTBLACalendar(const IslamicTBLACalendar& other) = default; 537 538 /** 539 * Destructor. 540 * @internal 541 */ 542 virtual ~IslamicTBLACalendar(); 543 544 /** 545 * @return The class ID for this object. All objects of a given class have the 546 * same class ID. Objects of other classes have different class IDs. 547 * @internal 548 */ 549 virtual UClassID getDynamicClassID() const override; 550 551 /** 552 * Return the class ID for this class. This is useful only for comparing to a return 553 * value from getDynamicClassID(). For example: 554 * 555 * Base* polymorphic_pointer = createPolymorphicObject(); 556 * if (polymorphic_pointer->getDynamicClassID() == 557 * Derived::getStaticClassID()) ... 558 * 559 * @return The class ID for all objects of this class. 560 * @internal 561 */ 562 static UClassID U_EXPORT2 getStaticClassID(); 563 564 /** 565 * return the calendar type, "islamic-tbla". 566 * 567 * @return calendar type 568 * @internal 569 */ 570 virtual const char * getType() const override; 571 572 // clone 573 virtual IslamicTBLACalendar* clone() const override; 574 575 protected: 576 /** 577 * Return the epoc. 578 * @internal 579 */ 580 virtual int32_t getEpoc() const override; 581 }; 582 583 /* 584 * IslamicUmalquraCalendar 585 * This calendar is referred as "Islamic calendar, Umm al-Qura" in CLDR. 586 */ 587 class U_I18N_API IslamicUmalquraCalendar : public IslamicCalendar { 588 public: 589 /** 590 * Constructs an IslamicUmalquraCalendar based on the current time in the default time zone 591 * with the given locale. 592 * 593 * @param aLocale The given locale. 594 * @param success Indicates the status of IslamicUmalquraCalendar object construction. 595 * Returns U_ZERO_ERROR if constructed successfully. 596 * @internal 597 */ 598 IslamicUmalquraCalendar(const Locale& aLocale, UErrorCode &success); 599 600 /** 601 * Copy Constructor 602 * @internal 603 */ 604 IslamicUmalquraCalendar(const IslamicUmalquraCalendar& other) = default; 605 606 /** 607 * Destructor. 608 * @internal 609 */ 610 virtual ~IslamicUmalquraCalendar(); 611 612 /** 613 * @return The class ID for this object. All objects of a given class have the 614 * same class ID. Objects of other classes have different class IDs. 615 * @internal 616 */ 617 virtual UClassID getDynamicClassID() const override; 618 619 /** 620 * Return the class ID for this class. This is useful only for comparing to a return 621 * value from getDynamicClassID(). For example: 622 * 623 * Base* polymorphic_pointer = createPolymorphicObject(); 624 * if (polymorphic_pointer->getDynamicClassID() == 625 * Derived::getStaticClassID()) ... 626 * 627 * @return The class ID for all objects of this class. 628 * @internal 629 */ 630 static UClassID U_EXPORT2 getStaticClassID(); 631 632 /** 633 * return the calendar type, "islamic-umalqura". 634 * 635 * @return calendar type 636 * @internal 637 */ 638 virtual const char * getType() const override; 639 640 // clone 641 virtual IslamicUmalquraCalendar* clone() const override; 642 643 protected: 644 /** 645 * Return the day # on which the given year starts. Days are counted 646 * from the Hijri epoch, origin 0. 647 * @internal 648 */ 649 virtual int32_t yearStart(int32_t year) const override; 650 651 /** 652 * Return the day # on which the given month starts. Days are counted 653 * from the Hijri epoch, origin 0. 654 * 655 * @param year The hijri year 656 * @param year The hijri month, 0-based 657 * @internal 658 */ 659 virtual int32_t monthStart(int32_t year, int32_t month) const override; 660 661 /** 662 * Return the length (in days) of the given month. 663 * 664 * @param year The hijri year 665 * @param year The hijri month, 0-based 666 * @internal 667 */ 668 virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month) const override; 669 670 /** 671 * Return the number of days in the given Islamic year 672 * @internal 673 */ 674 virtual int32_t handleGetYearLength(int32_t extendedYear) const override; 675 676 /** 677 * Override Calendar to compute several fields specific to the Islamic 678 * calendar system. These are: 679 * 680 * <ul><li>ERA 681 * <li>YEAR 682 * <li>MONTH 683 * <li>DAY_OF_MONTH 684 * <li>DAY_OF_YEAR 685 * <li>EXTENDED_YEAR</ul> 686 * 687 * The DAY_OF_WEEK and DOW_LOCAL fields are already set when this 688 * method is called. The getGregorianXxx() methods return Gregorian 689 * calendar equivalents for the given Julian day. 690 * @internal 691 */ 692 virtual void handleComputeFields(int32_t julianDay, UErrorCode &status) override; 693 }; 694 695 696 /* 697 * IslamicRGSACalendar 698 * Islamic calendar, Saudi Arabia sighting. Since the calendar depends on the 699 * sighting, it is impossible to implement by algorithm ahead of time. It is 700 * currently identical to IslamicCalendar except the getType will return 701 * "islamic-rgsa". 702 */ 703 class U_I18N_API IslamicRGSACalendar : public IslamicCalendar { 704 public: 705 /** 706 * Constructs an IslamicRGSACalendar based on the current time in the default time zone 707 * with the given locale. 708 * 709 * @param aLocale The given locale. 710 * @param success Indicates the status of IslamicRGSACalendar object construction. 711 * Returns U_ZERO_ERROR if constructed successfully. 712 * @internal 713 */ 714 IslamicRGSACalendar(const Locale& aLocale, UErrorCode &success); 715 716 /** 717 * Copy Constructor 718 * @internal 719 */ 720 IslamicRGSACalendar(const IslamicRGSACalendar& other) = default; 721 722 /** 723 * Destructor. 724 * @internal 725 */ 726 virtual ~IslamicRGSACalendar(); 727 728 /** 729 * @return The class ID for this object. All objects of a given class have the 730 * same class ID. Objects of other classes have different class IDs. 731 * @internal 732 */ 733 virtual UClassID getDynamicClassID() const override; 734 735 /** 736 * Return the class ID for this class. This is useful only for comparing to a return 737 * value from getDynamicClassID(). For example: 738 * 739 * Base* polymorphic_pointer = createPolymorphicObject(); 740 * if (polymorphic_pointer->getDynamicClassID() == 741 * Derived::getStaticClassID()) ... 742 * 743 * @return The class ID for all objects of this class. 744 * @internal 745 */ 746 static UClassID U_EXPORT2 getStaticClassID(); 747 748 /** 749 * return the calendar type, "islamic-rgsa". 750 * 751 * @return calendar type 752 * @internal 753 */ 754 virtual const char * getType() const override; 755 756 // clone 757 virtual IslamicRGSACalendar* clone() const override; 758 }; 759 760 U_NAMESPACE_END 761 762 #endif 763 #endif 764