@@ -95,10 +95,11 @@ pub struct HijriUmmAlQura {
95
95
#[ derive( Debug , Clone , Copy ) ]
96
96
pub struct HijriUmmAlQuraMarker ;
97
97
98
- /// The [tabular Hijri Calendar](https://en.wikipedia.org/wiki/Tabular_Islamic_calendar) (astronomical epoch)
98
+ /// The [tabular Hijri Calendar](https://en.wikipedia.org/wiki/Tabular_Islamic_calendar).
99
99
///
100
- /// This is a tabular/arithmetic Hijri calendar with leap years (1-based) 2, 5, 7, 10,
101
- /// 13, 16, 18, 21, 24, 26, and 29 in the 30-year cycle.
100
+ /// See [`HijriTabularEpoch`] and [`HijriTabularLeapYears`] for customization.
101
+ ///
102
+ /// The most common version of this calendar uses [`HijriTabularEpoch::Friday`] and [`HijriTabularLeapYears::TypeII`].
102
103
///
103
104
/// # Era codes
104
105
///
@@ -111,7 +112,10 @@ pub struct HijriUmmAlQuraMarker;
111
112
/// This calendar is a pure lunar calendar with no leap months. It uses month codes
112
113
/// `"M01" - "M12"`.
113
114
#[ derive( Copy , Clone , Debug , Hash , Eq , PartialEq , PartialOrd , Ord ) ]
114
- pub struct HijriTabular ( pub ( crate ) RataDie ) ;
115
+ pub struct HijriTabular {
116
+ pub ( crate ) epoch : HijriTabularEpoch ,
117
+ pub ( crate ) leap_years : HijriTabularLeapYears ,
118
+ }
115
119
116
120
impl HijriSimulated {
117
121
/// Creates a new [`HijriSimulated`] for reference location Mecca, with some compiled data containing precomputed calendrical calculations.
@@ -226,21 +230,40 @@ impl HijriUmmAlQura {
226
230
}
227
231
}
228
232
229
- impl HijriTabular {
230
- /// Construct a new [`HijriTabular`] with the civil/Friday epoch. That is,
231
- /// the year 1 starts on Friday July 16, 622 AD (0622-07-19 ISO).
232
- ///
233
- /// This is the most common version of the tabular Hijri calendar.
234
- pub const fn new_civil_epoch ( ) -> Self {
235
- Self ( ISLAMIC_EPOCH_FRIDAY )
233
+ /// The epoch for the [`HijriTabular`] calendar.
234
+ #[ non_exhaustive]
235
+ #[ derive( Copy , Clone , Debug , Hash , Eq , PartialEq , PartialOrd , Ord ) ]
236
+ pub enum HijriTabularEpoch {
237
+ /// Thusday July 15, 622 AD (0622-07-18 ISO)
238
+ Thursday ,
239
+ /// Friday July 16, 622 AD (0622-07-19 ISO)
240
+ Friday ,
241
+ }
242
+
243
+ impl HijriTabularEpoch {
244
+ fn rata_die ( self ) -> RataDie {
245
+ match self {
246
+ Self :: Thursday => ISLAMIC_EPOCH_THURSDAY ,
247
+ Self :: Friday => ISLAMIC_EPOCH_FRIDAY ,
248
+ }
236
249
}
250
+ }
237
251
238
- /// Construct a new [`HijriTabular`] with the astronomical/Thursday epoch.
239
- /// That is, the AH era starts on Thusday July 15, 622 AD (0622-07-18 ISO).
240
- ///
241
- /// This version of the calendar is also known as the "Microsoft Kuwaiti calendar".
242
- pub const fn new_astronomical_epoch ( ) -> Self {
243
- Self ( ISLAMIC_EPOCH_THURSDAY )
252
+ /// The leap year rule for the [`HijriTabular`] calendar.
253
+ ///
254
+ /// This specifies which years of a 30-year cycle have an additional day at
255
+ /// the end of the year.
256
+ #[ non_exhaustive]
257
+ #[ derive( Copy , Clone , Debug , Hash , Eq , PartialEq , PartialOrd , Ord ) ]
258
+ pub enum HijriTabularLeapYears {
259
+ /// Leap years 2, 5, 7, 10, 13, 16, 18, 21, 24, 26, 29
260
+ TypeII ,
261
+ }
262
+
263
+ impl HijriTabular {
264
+ /// Construct a new [`HijriTabular`] with the given epoch and leap year rule.
265
+ pub const fn new ( epoch : HijriTabularEpoch , leap_years : HijriTabularLeapYears ) -> Self {
266
+ Self { epoch, leap_years }
244
267
}
245
268
}
246
269
@@ -960,28 +983,39 @@ impl Calendar for HijriTabular {
960
983
) -> Result < Self :: DateInner , DateError > {
961
984
let year = match era {
962
985
Some ( "ah" ) | None => year,
963
- Some ( "islamic-civil" | "islamicc" ) if self . 0 == ISLAMIC_EPOCH_FRIDAY => year,
964
- Some ( "islamic-tbla" ) if self . 0 == ISLAMIC_EPOCH_THURSDAY => year,
986
+ Some ( "islamic-civil" | "islamicc" ) if self . epoch == HijriTabularEpoch :: Friday => year,
987
+ Some ( "islamic-tbla" ) if self . epoch == HijriTabularEpoch :: Thursday => year,
965
988
Some ( _) => return Err ( DateError :: UnknownEra ) ,
966
989
} ;
967
990
968
991
ArithmeticDate :: new_from_codes ( self , year, month_code, day) . map ( HijriTabularDateInner )
969
992
}
970
993
971
994
fn from_rata_die ( & self , rd : RataDie ) -> Self :: DateInner {
972
- let ( y, m, d) = calendrical_calculations:: islamic:: tabular_islamic_from_fixed ( rd, self . 0 ) ;
995
+ let ( y, m, d) = match self . leap_years {
996
+ HijriTabularLeapYears :: TypeII => {
997
+ calendrical_calculations:: islamic:: tabular_islamic_from_fixed (
998
+ rd,
999
+ self . epoch . rata_die ( ) ,
1000
+ )
1001
+ }
1002
+ } ;
973
1003
974
1004
debug_assert ! ( Date :: try_new_hijri_tabular_with_calendar( y, m, d, crate :: Ref ( self ) ) . is_ok( ) ) ;
975
1005
HijriTabularDateInner ( ArithmeticDate :: new_unchecked ( y, m, d) )
976
1006
}
977
1007
978
1008
fn to_rata_die ( & self , date : & Self :: DateInner ) -> RataDie {
979
- calendrical_calculations:: islamic:: fixed_from_tabular_islamic (
980
- date. 0 . year ,
981
- date. 0 . month ,
982
- date. 0 . day ,
983
- self . 0 ,
984
- )
1009
+ match self . leap_years {
1010
+ HijriTabularLeapYears :: TypeII => {
1011
+ calendrical_calculations:: islamic:: fixed_from_tabular_islamic (
1012
+ date. 0 . year ,
1013
+ date. 0 . month ,
1014
+ date. 0 . day ,
1015
+ self . epoch . rata_die ( ) ,
1016
+ )
1017
+ }
1018
+ }
985
1019
}
986
1020
987
1021
fn from_iso ( & self , iso : IsoDateInner ) -> Self :: DateInner {
@@ -1020,18 +1054,17 @@ impl Calendar for HijriTabular {
1020
1054
}
1021
1055
1022
1056
fn debug_name ( & self ) -> & ' static str {
1023
- match self . 0 {
1024
- ISLAMIC_EPOCH_FRIDAY => "Hijri (civil)" ,
1025
- _ => "Hijri (astronomical)" ,
1057
+ match self . epoch {
1058
+ HijriTabularEpoch :: Friday => "Hijri (civil)" ,
1059
+ HijriTabularEpoch :: Thursday => "Hijri (astronomical)" ,
1026
1060
}
1027
1061
}
1028
1062
1029
1063
fn year ( & self , date : & Self :: DateInner ) -> types:: YearInfo {
1030
1064
year_as_hijri (
1031
- if self . 0 == ISLAMIC_EPOCH_FRIDAY {
1032
- tinystr ! ( 16 , "islamic-civil" )
1033
- } else {
1034
- tinystr ! ( 16 , "islamic-tbla" )
1065
+ match self . epoch {
1066
+ HijriTabularEpoch :: Friday => tinystr ! ( 16 , "islamic-civil" ) ,
1067
+ HijriTabularEpoch :: Thursday => tinystr ! ( 16 , "islamic-tbla" ) ,
1035
1068
} ,
1036
1069
date. 0 . year ,
1037
1070
)
@@ -1064,10 +1097,10 @@ impl<A: AsCalendar<Calendar = HijriTabular>> Date<A> {
1064
1097
/// Has no negative years, only era is the AH.
1065
1098
///
1066
1099
/// ```rust
1067
- /// use icu::calendar::cal::HijriTabular;
1100
+ /// use icu::calendar::cal::{ HijriTabular, HijriTabularEpoch, HijriTabularLeapYears} ;
1068
1101
/// use icu::calendar::Date;
1069
1102
///
1070
- /// let hijri = HijriTabular::new_civil_epoch( );
1103
+ /// let hijri = HijriTabular::new(HijriTabularEpoch::Thursday, HijriTabularLeapYears::TypeII );
1071
1104
///
1072
1105
/// let date_hijri =
1073
1106
/// Date::try_new_hijri_tabular_with_calendar(1392, 4, 25, hijri)
@@ -1814,7 +1847,7 @@ mod test {
1814
1847
1815
1848
#[ test]
1816
1849
fn test_rd_from_hijri ( ) {
1817
- let calendar = HijriTabular :: new_civil_epoch ( ) ;
1850
+ let calendar = HijriTabular :: new ( HijriTabularEpoch :: Friday , HijriTabularLeapYears :: TypeII ) ;
1818
1851
let calendar = Ref ( & calendar) ;
1819
1852
for ( case, f_date) in ARITHMETIC_CASES . iter ( ) . zip ( TEST_RD . iter ( ) ) {
1820
1853
let date = Date :: try_new_hijri_tabular_with_calendar (
@@ -1827,7 +1860,7 @@ mod test {
1827
1860
1828
1861
#[ test]
1829
1862
fn test_hijri_from_rd ( ) {
1830
- let calendar = HijriTabular :: new_civil_epoch ( ) ;
1863
+ let calendar = HijriTabular :: new ( HijriTabularEpoch :: Friday , HijriTabularLeapYears :: TypeII ) ;
1831
1864
let calendar = Ref ( & calendar) ;
1832
1865
for ( case, f_date) in ARITHMETIC_CASES . iter ( ) . zip ( TEST_RD . iter ( ) ) {
1833
1866
let date = Date :: try_new_hijri_tabular_with_calendar (
@@ -1842,7 +1875,8 @@ mod test {
1842
1875
1843
1876
#[ test]
1844
1877
fn test_rd_from_hijri_tbla ( ) {
1845
- let calendar = HijriTabular :: new_astronomical_epoch ( ) ;
1878
+ let calendar =
1879
+ HijriTabular :: new ( HijriTabularEpoch :: Thursday , HijriTabularLeapYears :: TypeII ) ;
1846
1880
let calendar = Ref ( & calendar) ;
1847
1881
for ( case, f_date) in ASTRONOMICAL_CASES . iter ( ) . zip ( TEST_RD . iter ( ) ) {
1848
1882
let date = Date :: try_new_hijri_tabular_with_calendar (
@@ -1855,7 +1889,8 @@ mod test {
1855
1889
1856
1890
#[ test]
1857
1891
fn test_hijri_tbla_from_rd ( ) {
1858
- let calendar = HijriTabular :: new_astronomical_epoch ( ) ;
1892
+ let calendar =
1893
+ HijriTabular :: new ( HijriTabularEpoch :: Thursday , HijriTabularLeapYears :: TypeII ) ;
1859
1894
let calendar = Ref ( & calendar) ;
1860
1895
for ( case, f_date) in ASTRONOMICAL_CASES . iter ( ) . zip ( TEST_RD . iter ( ) ) {
1861
1896
let date = Date :: try_new_hijri_tabular_with_calendar (
0 commit comments