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 * Return the day # on which the given year starts. Days are counted 202 * from the Hijri epoch, origin 0. 203 */ 204 virtual int64_t yearStart(int32_t year) const; 205 206 /** 207 * Return the day # on which the given month starts. Days are counted 208 * from the Hijri epoch, origin 0. 209 * 210 * @param year The hijri year 211 * @param year The hijri month, 0-based 212 */ 213 virtual int64_t monthStart(int32_t year, int32_t month, UErrorCode& status) const; 214 215 216 //---------------------------------------------------------------------- 217 // Calendar framework 218 //---------------------------------------------------------------------- 219 protected: 220 /** 221 * @internal 222 */ 223 virtual int32_t handleGetLimit(UCalendarDateFields field, ELimitType limitType) const override; 224 225 /** 226 * Return the length (in days) of the given month. 227 * 228 * @param year The hijri year 229 * @param year The hijri month, 0-based 230 * @internal 231 */ 232 virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month, UErrorCode& status) const override; 233 234 /** 235 * Return the number of days in the given Islamic year 236 * @internal 237 */ 238 virtual int32_t handleGetYearLength(int32_t extendedYear) const override; 239 240 //------------------------------------------------------------------------- 241 // Functions for converting from field values to milliseconds.... 242 //------------------------------------------------------------------------- 243 244 // Return JD of start of given month/year 245 /** 246 * @internal 247 */ 248 virtual int64_t handleComputeMonthStart(int32_t eyear, int32_t month, UBool useMonth, UErrorCode& status) const override; 249 250 //------------------------------------------------------------------------- 251 // Functions for converting from milliseconds to field values 252 //------------------------------------------------------------------------- 253 254 /** 255 * @internal 256 */ 257 virtual int32_t handleGetExtendedYear(UErrorCode& status) override; 258 259 /** 260 * Override Calendar to compute several fields specific to the Islamic 261 * calendar system. These are: 262 * 263 * <ul><li>ERA 264 * <li>YEAR 265 * <li>MONTH 266 * <li>DAY_OF_MONTH 267 * <li>DAY_OF_YEAR 268 * <li>EXTENDED_YEAR</ul> 269 * 270 * The DAY_OF_WEEK and DOW_LOCAL fields are already set when this 271 * method is called. The getGregorianXxx() methods return Gregorian 272 * calendar equivalents for the given Julian day. 273 * @internal 274 */ 275 virtual void handleComputeFields(int32_t julianDay, UErrorCode &status) override; 276 277 /** 278 * Return the epoc. 279 * @internal 280 */ 281 virtual int32_t getEpoc() const; 282 283 // UObject stuff 284 public: 285 /** 286 * @return The class ID for this object. All objects of a given class have the 287 * same class ID. Objects of other classes have different class IDs. 288 * @internal 289 */ 290 virtual UClassID getDynamicClassID() const override; 291 292 /** 293 * Return the class ID for this class. This is useful only for comparing to a return 294 * value from getDynamicClassID(). For example: 295 * 296 * Base* polymorphic_pointer = createPolymorphicObject(); 297 * if (polymorphic_pointer->getDynamicClassID() == 298 * Derived::getStaticClassID()) ... 299 * 300 * @return The class ID for all objects of this class. 301 * @internal 302 */ 303 /*U_I18N_API*/ static UClassID U_EXPORT2 getStaticClassID(); 304 305 /** 306 * return the calendar type, "islamic". 307 * 308 * @return calendar type 309 * @internal 310 */ 311 virtual const char * getType() const override; 312 313 /** 314 * @return The related Gregorian year; will be obtained by modifying the value 315 * obtained by get from UCAL_EXTENDED_YEAR field 316 * @internal 317 */ 318 virtual int32_t getRelatedYear(UErrorCode &status) const override; 319 320 /** 321 * @param year The related Gregorian year to set; will be modified as necessary then 322 * set in UCAL_EXTENDED_YEAR field 323 * @internal 324 */ 325 virtual void setRelatedYear(int32_t year) override; 326 327 /** 328 * Returns true if the date is in a leap year. 329 * 330 * @param status ICU Error Code 331 * @return True if the date in the fields is in a Temporal proposal 332 * defined leap year. False otherwise. 333 */ 334 virtual bool inTemporalLeapYear(UErrorCode &status) const override; 335 336 private: 337 IslamicCalendar() = delete; // default constructor not implemented 338 339 // Default century. 340 protected: 341 342 DECLARE_OVERRIDE_SYSTEM_DEFAULT_CENTURY 343 }; 344 345 /* 346 * IslamicCivilCalendar is one of the two main variants of the Islamic calendar. 347 * The <em>civil</em> calendar, which uses a fixed cycle of alternating 29- 348 * and 30-day months, with a leap day added to the last month of 11 out of 349 * every 30 years. This calendar is easily calculated and thus predictable in 350 * advance, so it is used as the civil calendar in a number of Arab countries. 351 * This calendar is referring as "Islamic calendar, tabular (intercalary years 352 * [2,5,7,10,13,16,18,21,24,26,29]- civil epoch" in CLDR. 353 */ 354 class U_I18N_API IslamicCivilCalendar : public IslamicCalendar { 355 public: 356 /** 357 * Constructs an IslamicCivilCalendar based on the current time in the default time zone 358 * with the given locale. 359 * 360 * @param aLocale The given locale. 361 * @param success Indicates the status of IslamicCivilCalendar object construction. 362 * Returns U_ZERO_ERROR if constructed successfully. 363 * @internal 364 */ 365 IslamicCivilCalendar(const Locale& aLocale, UErrorCode &success); 366 367 /** 368 * Copy Constructor 369 * @internal 370 */ 371 IslamicCivilCalendar(const IslamicCivilCalendar& other) = default; 372 373 /** 374 * Destructor. 375 * @internal 376 */ 377 virtual ~IslamicCivilCalendar(); 378 379 // clone 380 virtual IslamicCivilCalendar* clone() const override; 381 382 /** 383 * @return The class ID for this object. All objects of a given class have the 384 * same class ID. Objects of other classes have different class IDs. 385 * @internal 386 */ 387 virtual UClassID getDynamicClassID() const override; 388 389 /** 390 * Return the class ID for this class. This is useful only for comparing to a return 391 * value from getDynamicClassID(). For example: 392 * 393 * Base* polymorphic_pointer = createPolymorphicObject(); 394 * if (polymorphic_pointer->getDynamicClassID() == 395 * Derived::getStaticClassID()) ... 396 * 397 * @return The class ID for all objects of this class. 398 * @internal 399 */ 400 static UClassID U_EXPORT2 getStaticClassID(); 401 402 /** 403 * return the calendar type, "islamic-civil". 404 * 405 * @return calendar type 406 * @internal 407 */ 408 virtual const char * getType() const override; 409 410 protected: 411 /** 412 * Return the day # on which the given year starts. Days are counted 413 * from the Hijri epoch, origin 0. 414 * @internal 415 */ 416 virtual int64_t yearStart(int32_t year) const override; 417 418 /** 419 * Return the day # on which the given month starts. Days are counted 420 * from the Hijri epoch, origin 0. 421 * 422 * @param year The hijri year 423 * @param year The hijri month, 0-based 424 * @internal 425 */ 426 virtual int64_t monthStart(int32_t year, int32_t month, UErrorCode& status) const override; 427 428 /** 429 * Return the length (in days) of the given month. 430 * 431 * @param year The hijri year 432 * @param year The hijri month, 0-based 433 * @internal 434 */ 435 virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month, UErrorCode& status) const override; 436 437 /** 438 * Return the number of days in the given Islamic year 439 * @internal 440 */ 441 virtual int32_t handleGetYearLength(int32_t extendedYear) const override; 442 443 /** 444 * Override Calendar to compute several fields specific to the Islamic 445 * calendar system. These are: 446 * 447 * <ul><li>ERA 448 * <li>YEAR 449 * <li>MONTH 450 * <li>DAY_OF_MONTH 451 * <li>DAY_OF_YEAR 452 * <li>EXTENDED_YEAR</ul> 453 * 454 * The DAY_OF_WEEK and DOW_LOCAL fields are already set when this 455 * method is called. The getGregorianXxx() methods return Gregorian 456 * calendar equivalents for the given Julian day. 457 * @internal 458 */ 459 virtual void handleComputeFields(int32_t julianDay, UErrorCode &status) override; 460 }; 461 462 /* 463 * IslamicTBLACalendar calendar. 464 * This is a subclass of IslamicCivilCalendar. The only differences in the 465 * calendar math is it uses different epoch. 466 * This calendar is referring as "Islamic calendar, tabular (intercalary years 467 * [2,5,7,10,13,16,18,21,24,26,29] - astronomical epoch" in CLDR. 468 */ 469 class U_I18N_API IslamicTBLACalendar : public IslamicCivilCalendar { 470 public: 471 /** 472 * Constructs an IslamicTBLACalendar based on the current time in the default time zone 473 * with the given locale. 474 * 475 * @param aLocale The given locale. 476 * @param success Indicates the status of IslamicTBLACalendar object construction. 477 * Returns U_ZERO_ERROR if constructed successfully. 478 * @internal 479 */ 480 IslamicTBLACalendar(const Locale& aLocale, UErrorCode &success); 481 482 /** 483 * Copy Constructor 484 * @internal 485 */ 486 IslamicTBLACalendar(const IslamicTBLACalendar& other) = default; 487 488 /** 489 * Destructor. 490 * @internal 491 */ 492 virtual ~IslamicTBLACalendar(); 493 494 /** 495 * @return The class ID for this object. All objects of a given class have the 496 * same class ID. Objects of other classes have different class IDs. 497 * @internal 498 */ 499 virtual UClassID getDynamicClassID() const override; 500 501 /** 502 * Return the class ID for this class. This is useful only for comparing to a return 503 * value from getDynamicClassID(). For example: 504 * 505 * Base* polymorphic_pointer = createPolymorphicObject(); 506 * if (polymorphic_pointer->getDynamicClassID() == 507 * Derived::getStaticClassID()) ... 508 * 509 * @return The class ID for all objects of this class. 510 * @internal 511 */ 512 static UClassID U_EXPORT2 getStaticClassID(); 513 514 /** 515 * return the calendar type, "islamic-tbla". 516 * 517 * @return calendar type 518 * @internal 519 */ 520 virtual const char * getType() const override; 521 522 // clone 523 virtual IslamicTBLACalendar* clone() const override; 524 525 protected: 526 /** 527 * Return the epoc. 528 * @internal 529 */ 530 virtual int32_t getEpoc() const override; 531 }; 532 533 /* 534 * IslamicUmalquraCalendar 535 * This calendar is referred as "Islamic calendar, Umm al-Qura" in CLDR. 536 */ 537 class U_I18N_API IslamicUmalquraCalendar : public IslamicCivilCalendar { 538 public: 539 /** 540 * Constructs an IslamicUmalquraCalendar based on the current time in the default time zone 541 * with the given locale. 542 * 543 * @param aLocale The given locale. 544 * @param success Indicates the status of IslamicUmalquraCalendar object construction. 545 * Returns U_ZERO_ERROR if constructed successfully. 546 * @internal 547 */ 548 IslamicUmalquraCalendar(const Locale& aLocale, UErrorCode &success); 549 550 /** 551 * Copy Constructor 552 * @internal 553 */ 554 IslamicUmalquraCalendar(const IslamicUmalquraCalendar& other) = default; 555 556 /** 557 * Destructor. 558 * @internal 559 */ 560 virtual ~IslamicUmalquraCalendar(); 561 562 /** 563 * @return The class ID for this object. All objects of a given class have the 564 * same class ID. Objects of other classes have different class IDs. 565 * @internal 566 */ 567 virtual UClassID getDynamicClassID() const override; 568 569 /** 570 * Return the class ID for this class. This is useful only for comparing to a return 571 * value from getDynamicClassID(). For example: 572 * 573 * Base* polymorphic_pointer = createPolymorphicObject(); 574 * if (polymorphic_pointer->getDynamicClassID() == 575 * Derived::getStaticClassID()) ... 576 * 577 * @return The class ID for all objects of this class. 578 * @internal 579 */ 580 static UClassID U_EXPORT2 getStaticClassID(); 581 582 /** 583 * return the calendar type, "islamic-umalqura". 584 * 585 * @return calendar type 586 * @internal 587 */ 588 virtual const char * getType() const override; 589 590 // clone 591 virtual IslamicUmalquraCalendar* clone() const override; 592 593 protected: 594 /** 595 * Return the day # on which the given year starts. Days are counted 596 * from the Hijri epoch, origin 0. 597 * @internal 598 */ 599 virtual int64_t yearStart(int32_t year) const override; 600 601 /** 602 * Return the day # on which the given month starts. Days are counted 603 * from the Hijri epoch, origin 0. 604 * 605 * @param year The hijri year 606 * @param year The hijri month, 0-based 607 * @internal 608 */ 609 virtual int64_t monthStart(int32_t year, int32_t month, UErrorCode& status) const override; 610 611 /** 612 * Return the length (in days) of the given month. 613 * 614 * @param year The hijri year 615 * @param year The hijri month, 0-based 616 * @internal 617 */ 618 virtual int32_t handleGetMonthLength(int32_t extendedYear, int32_t month, UErrorCode& status) const override; 619 620 /** 621 * Return the number of days in the given Islamic year 622 * @internal 623 */ 624 virtual int32_t handleGetYearLength(int32_t extendedYear) const override; 625 626 /** 627 * Override Calendar to compute several fields specific to the Islamic 628 * calendar system. These are: 629 * 630 * <ul><li>ERA 631 * <li>YEAR 632 * <li>MONTH 633 * <li>DAY_OF_MONTH 634 * <li>DAY_OF_YEAR 635 * <li>EXTENDED_YEAR</ul> 636 * 637 * The DAY_OF_WEEK and DOW_LOCAL fields are already set when this 638 * method is called. The getGregorianXxx() methods return Gregorian 639 * calendar equivalents for the given Julian day. 640 * @internal 641 */ 642 virtual void handleComputeFields(int32_t julianDay, UErrorCode &status) override; 643 }; 644 645 646 /* 647 * IslamicRGSACalendar 648 * Islamic calendar, Saudi Arabia sighting. Since the calendar depends on the 649 * sighting, it is impossible to implement by algorithm ahead of time. It is 650 * currently identical to IslamicCalendar except the getType will return 651 * "islamic-rgsa". 652 */ 653 class U_I18N_API IslamicRGSACalendar : public IslamicCalendar { 654 public: 655 /** 656 * Constructs an IslamicRGSACalendar based on the current time in the default time zone 657 * with the given locale. 658 * 659 * @param aLocale The given locale. 660 * @param success Indicates the status of IslamicRGSACalendar object construction. 661 * Returns U_ZERO_ERROR if constructed successfully. 662 * @internal 663 */ 664 IslamicRGSACalendar(const Locale& aLocale, UErrorCode &success); 665 666 /** 667 * Copy Constructor 668 * @internal 669 */ 670 IslamicRGSACalendar(const IslamicRGSACalendar& other) = default; 671 672 /** 673 * Destructor. 674 * @internal 675 */ 676 virtual ~IslamicRGSACalendar(); 677 678 /** 679 * @return The class ID for this object. All objects of a given class have the 680 * same class ID. Objects of other classes have different class IDs. 681 * @internal 682 */ 683 virtual UClassID getDynamicClassID() const override; 684 685 /** 686 * Return the class ID for this class. This is useful only for comparing to a return 687 * value from getDynamicClassID(). For example: 688 * 689 * Base* polymorphic_pointer = createPolymorphicObject(); 690 * if (polymorphic_pointer->getDynamicClassID() == 691 * Derived::getStaticClassID()) ... 692 * 693 * @return The class ID for all objects of this class. 694 * @internal 695 */ 696 static UClassID U_EXPORT2 getStaticClassID(); 697 698 /** 699 * return the calendar type, "islamic-rgsa". 700 * 701 * @return calendar type 702 * @internal 703 */ 704 virtual const char * getType() const override; 705 706 // clone 707 virtual IslamicRGSACalendar* clone() const override; 708 }; 709 710 U_NAMESPACE_END 711 712 #endif 713 #endif 714