Coverage Report

Created: 2026-01-22 06:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/icu/icu4c/source/i18n/islamcal.h
Line
Count
Source
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
5.80k
  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, UErrorCode& status) 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, UErrorCode& status) 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
3.83k
  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, UErrorCode& status) 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, UErrorCode& status) 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
1.00k
  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
1.64k
  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, UErrorCode& status) 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, UErrorCode& status) 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
 private:
645
  virtual int32_t yearLength(int32_t extendedYear, UErrorCode& status) const;
646
};
647
648
649
/*
650
 * IslamicRGSACalendar
651
 * Islamic calendar, Saudi Arabia sighting. Since the calendar depends on the
652
 * sighting, it is impossible to implement by algorithm ahead of time. It is
653
 * currently identical to IslamicCalendar except the getType will return
654
 * "islamic-rgsa".
655
 */
656
class U_I18N_API IslamicRGSACalendar : public IslamicCalendar {
657
 public:
658
  /**
659
   * Constructs an IslamicRGSACalendar based on the current time in the default time zone
660
   * with the given locale.
661
   *
662
   * @param aLocale  The given locale.
663
   * @param success  Indicates the status of IslamicRGSACalendar object construction.
664
   *                 Returns U_ZERO_ERROR if constructed successfully.
665
   * @internal
666
   */
667
  IslamicRGSACalendar(const Locale& aLocale, UErrorCode &success);
668
669
  /**
670
   * Copy Constructor
671
   * @internal
672
   */
673
0
  IslamicRGSACalendar(const IslamicRGSACalendar& other) = default;
674
675
  /**
676
   * Destructor.
677
   * @internal
678
   */
679
  virtual ~IslamicRGSACalendar();
680
681
  /**
682
   * @return   The class ID for this object. All objects of a given class have the
683
   *           same class ID. Objects of other classes have different class IDs.
684
   * @internal
685
   */
686
  virtual UClassID getDynamicClassID() const override;
687
688
  /**
689
   * Return the class ID for this class. This is useful only for comparing to a return
690
   * value from getDynamicClassID(). For example:
691
   *
692
   *      Base* polymorphic_pointer = createPolymorphicObject();
693
   *      if (polymorphic_pointer->getDynamicClassID() ==
694
   *          Derived::getStaticClassID()) ...
695
   *
696
   * @return   The class ID for all objects of this class.
697
   * @internal
698
   */
699
  static UClassID U_EXPORT2 getStaticClassID();
700
701
  /**
702
   * return the calendar type, "islamic-rgsa".
703
   *
704
   * @return calendar type
705
   * @internal
706
   */
707
  virtual const char * getType() const override;
708
709
  // clone
710
  virtual IslamicRGSACalendar* clone() const override;
711
};
712
713
U_NAMESPACE_END
714
715
#endif
716
#endif