Skip to content

Commit c0cea90

Browse files
committed
related gregorian
1 parent e0c2dad commit c0cea90

File tree

17 files changed

+301
-20
lines changed

17 files changed

+301
-20
lines changed

components/calendar/src/cal/abstract_gregorian.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,13 @@ pub(crate) trait GregorianYears: Clone + core::fmt::Debug {
2222
fn extended_from_era_year(&self, era: Option<&[u8]>, year: i32)
2323
-> Result<i32, UnknownEraError>;
2424

25-
fn era_year_from_extended(&self, extended_year: i32, month: u8, day: u8) -> EraYear;
25+
fn era_year_from_extended(
26+
&self,
27+
extended_year: i32,
28+
related_gregorian: i32,
29+
month: u8,
30+
day: u8,
31+
) -> EraYear;
2632

2733
fn calendar_algorithm(&self) -> Option<CalendarAlgorithm> {
2834
None
@@ -164,6 +170,7 @@ impl<Y: GregorianYears> Calendar for AbstractGregorian<Y> {
164170
fn year_info(&self, date: &Self::DateInner) -> Self::Year {
165171
self.0.era_year_from_extended(
166172
date.year() - Y::EXTENDED_YEAR_OFFSET,
173+
date.year(),
167174
date.month(),
168175
date.day(),
169176
)

components/calendar/src/cal/buddhist.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,18 @@ impl GregorianYears for BuddhistEra {
5555
}
5656
}
5757

58-
fn era_year_from_extended(&self, extended_year: i32, _month: u8, _day: u8) -> types::EraYear {
58+
fn era_year_from_extended(
59+
&self,
60+
extended_year: i32,
61+
related_gregorian: i32,
62+
_month: u8,
63+
_day: u8,
64+
) -> types::EraYear {
5965
types::EraYear {
6066
era: tinystr!(16, "be"),
6167
era_index: Some(0),
6268
year: extended_year,
69+
related_gregorian,
6370
extended_year,
6471
ambiguity: types::YearAmbiguity::CenturyRequired,
6572
}

components/calendar/src/cal/coptic.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,10 +200,15 @@ impl Calendar for Coptic {
200200

201201
fn year_info(&self, date: &Self::DateInner) -> Self::Year {
202202
let year = date.0.year();
203+
let related_gregorian = calendrical_calculations::gregorian::year_from_fixed(
204+
calendrical_calculations::coptic::fixed_from_coptic(year, 1, 1),
205+
)
206+
.unwrap_or_else(|e| e.saturate());
203207
types::EraYear {
204208
era: tinystr!(16, "am"),
205209
era_index: Some(0),
206210
year,
211+
related_gregorian,
207212
extended_year: year,
208213
ambiguity: types::YearAmbiguity::CenturyRequired,
209214
}
@@ -289,4 +294,41 @@ mod tests {
289294
let date = Date::try_from_fields(fields, options, Coptic).unwrap();
290295
assert_eq!(date.day_of_month().0, 6, "Day was successfully constrained");
291296
}
297+
298+
#[test]
299+
fn related_gregorian() {
300+
assert_eq!(
301+
Date::try_new_gregorian(2025, 8, 18)
302+
.unwrap()
303+
.to_calendar(Coptic)
304+
.era_year()
305+
.related_gregorian,
306+
2024
307+
);
308+
assert_eq!(
309+
Date::try_new_gregorian(2025, 9, 18)
310+
.unwrap()
311+
.to_calendar(Coptic)
312+
.era_year()
313+
.related_gregorian,
314+
2025
315+
);
316+
317+
// By 16702 the Coptic calendar is a full year ahead
318+
// of the Gregorian calendar
319+
assert_eq!(
320+
Date::try_new_coptic(16419, 1, 1)
321+
.unwrap()
322+
.era_year()
323+
.related_gregorian,
324+
16702
325+
);
326+
assert_eq!(
327+
Date::try_new_coptic(16420, 1, 1)
328+
.unwrap()
329+
.era_year()
330+
.related_gregorian,
331+
16704
332+
);
333+
}
292334
}

components/calendar/src/cal/ethiopian.rs

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -207,26 +207,28 @@ impl Calendar for Ethiopian {
207207
}
208208

209209
fn year_info(&self, date: &Self::DateInner) -> Self::Year {
210-
let coptic_year = date.0 .0.year();
210+
let coptic_year = Coptic.year_info(&date.0);
211211
let extended_year = if self.0 == EthiopianEraStyle::AmeteAlem {
212-
coptic_year - AMETE_ALEM_OFFSET
212+
coptic_year.extended_year - AMETE_ALEM_OFFSET
213213
} else {
214-
coptic_year - AMETE_MIHRET_OFFSET
214+
coptic_year.extended_year - AMETE_MIHRET_OFFSET
215215
};
216216

217217
if self.0 == EthiopianEraStyle::AmeteAlem || extended_year <= 0 {
218218
types::EraYear {
219219
era: tinystr!(16, "aa"),
220220
era_index: Some(0),
221-
year: coptic_year - AMETE_ALEM_OFFSET,
221+
year: coptic_year.year - AMETE_ALEM_OFFSET,
222+
related_gregorian: coptic_year.related_gregorian,
222223
extended_year,
223224
ambiguity: types::YearAmbiguity::CenturyRequired,
224225
}
225226
} else {
226227
types::EraYear {
227228
era: tinystr!(16, "am"),
228229
era_index: Some(1),
229-
year: coptic_year - AMETE_MIHRET_OFFSET,
230+
year: coptic_year.year - AMETE_MIHRET_OFFSET,
231+
related_gregorian: coptic_year.related_gregorian,
230232
extended_year,
231233
ambiguity: types::YearAmbiguity::CenturyRequired,
232234
}
@@ -390,4 +392,41 @@ mod test {
390392
1
391393
);
392394
}
395+
396+
#[test]
397+
fn related_gregorian() {
398+
assert_eq!(
399+
Date::try_new_gregorian(2025, 8, 18)
400+
.unwrap()
401+
.to_calendar(Ethiopian::new())
402+
.era_year()
403+
.related_gregorian,
404+
2024
405+
);
406+
assert_eq!(
407+
Date::try_new_gregorian(2025, 9, 18)
408+
.unwrap()
409+
.to_calendar(Ethiopian::new())
410+
.era_year()
411+
.related_gregorian,
412+
2025
413+
);
414+
415+
// By 16702 the Ethiopian calendar is a full year ahead
416+
// of the Gregorian calendar
417+
assert_eq!(
418+
Date::try_new_ethiopian(EthiopianEraStyle::AmeteMihret, 16695, 1, 1)
419+
.unwrap()
420+
.era_year()
421+
.related_gregorian,
422+
16702
423+
);
424+
assert_eq!(
425+
Date::try_new_ethiopian(EthiopianEraStyle::AmeteMihret, 16696, 1, 1)
426+
.unwrap()
427+
.era_year()
428+
.related_gregorian,
429+
16704
430+
);
431+
}
393432
}

components/calendar/src/cal/gregorian.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,19 @@ impl GregorianYears for CeBce {
3030
}
3131
}
3232

33-
fn era_year_from_extended(&self, extended_year: i32, _month: u8, _day: u8) -> types::EraYear {
33+
fn era_year_from_extended(
34+
&self,
35+
extended_year: i32,
36+
related_gregorian: i32,
37+
_month: u8,
38+
_day: u8,
39+
) -> types::EraYear {
3440
if extended_year > 0 {
3541
types::EraYear {
3642
era: tinystr!(16, "ce"),
3743
era_index: Some(1),
3844
year: extended_year,
45+
related_gregorian,
3946
extended_year,
4047
ambiguity: match extended_year {
4148
..=999 => types::YearAmbiguity::EraAndCenturyRequired,
@@ -49,6 +56,7 @@ impl GregorianYears for CeBce {
4956
era: tinystr!(16, "bce"),
5057
era_index: Some(0),
5158
year: 1 - extended_year,
59+
related_gregorian,
5260
extended_year,
5361
ambiguity: types::YearAmbiguity::EraAndCenturyRequired,
5462
}

components/calendar/src/cal/hebrew.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,10 +316,14 @@ impl Calendar for Hebrew {
316316

317317
fn year_info(&self, date: &Self::DateInner) -> Self::Year {
318318
let extended_year = date.0.year().value;
319+
let related_gregorian =
320+
calendrical_calculations::gregorian::year_from_fixed(date.0.year().new_year())
321+
.unwrap_or_else(|e| e.saturate());
319322
types::EraYear {
320323
era_index: Some(0),
321324
era: tinystr!(16, "am"),
322325
year: extended_year,
326+
related_gregorian,
323327
extended_year,
324328
ambiguity: types::YearAmbiguity::CenturyRequired,
325329
}
@@ -524,4 +528,41 @@ mod tests {
524528
// https://www.hebcal.com/converter?hd=1&hm=Tishrei&hy=3760&h2g=1
525529
assert_eq!(dt.weekday(), Weekday::Saturday);
526530
}
531+
532+
#[test]
533+
fn related_gregorian() {
534+
assert_eq!(
535+
Date::try_new_gregorian(2025, 9, 18)
536+
.unwrap()
537+
.to_calendar(Hebrew)
538+
.era_year()
539+
.related_gregorian,
540+
2024
541+
);
542+
assert_eq!(
543+
Date::try_new_gregorian(2025, 10, 18)
544+
.unwrap()
545+
.to_calendar(Hebrew)
546+
.era_year()
547+
.related_gregorian,
548+
2025
549+
);
550+
551+
// By 22203 the Hebrew calendar is a full year ahead
552+
// of the Gregorian calendar
553+
assert_eq!(
554+
Date::try_new_from_codes(None, 25962, TISHREI.code(), 1, Hebrew)
555+
.unwrap()
556+
.era_year()
557+
.related_gregorian,
558+
22201
559+
);
560+
assert_eq!(
561+
Date::try_new_from_codes(None, 25963, TISHREI.code(), 1, Hebrew)
562+
.unwrap()
563+
.era_year()
564+
.related_gregorian,
565+
22203
566+
);
567+
}
527568
}

components/calendar/src/cal/hijri.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -911,11 +911,15 @@ impl<R: Rules> Calendar for Hijri<R> {
911911

912912
fn year_info(&self, date: &Self::DateInner) -> Self::Year {
913913
let extended_year = date.0.year().extended_year;
914+
let related_gregorian =
915+
calendrical_calculations::gregorian::year_from_fixed(date.0.year().new_year())
916+
.unwrap_or_else(|e| e.saturate());
914917
if extended_year > 0 {
915918
types::EraYear {
916919
era: tinystr!(16, "ah"),
917920
era_index: Some(0),
918921
year: extended_year,
922+
related_gregorian,
919923
extended_year,
920924
ambiguity: types::YearAmbiguity::CenturyRequired,
921925
}
@@ -925,6 +929,7 @@ impl<R: Rules> Calendar for Hijri<R> {
925929
era_index: Some(1),
926930
year: 1 - extended_year,
927931
extended_year,
932+
related_gregorian,
928933
ambiguity: types::YearAmbiguity::CenturyRequired,
929934
}
930935
}
@@ -1951,4 +1956,24 @@ mod test {
19511956
single_roundtrip(mixed2, start_1600 - 1).unwrap();
19521957
single_roundtrip(mixed2, start_1600 - 4).unwrap();
19531958
}
1959+
1960+
#[test]
1961+
fn related_gregorian() {
1962+
assert_eq!(
1963+
Date::try_new_gregorian(2025, 6, 18)
1964+
.unwrap()
1965+
.to_calendar(Hijri::new_umm_al_qura())
1966+
.era_year()
1967+
.related_gregorian,
1968+
2024
1969+
);
1970+
assert_eq!(
1971+
Date::try_new_gregorian(2025, 7, 18)
1972+
.unwrap()
1973+
.to_calendar(Hijri::new_umm_al_qura())
1974+
.era_year()
1975+
.related_gregorian,
1976+
2025
1977+
);
1978+
}
19541979
}

components/calendar/src/cal/indian.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ impl Calendar for Indian {
244244
era: tinystr!(16, "shaka"),
245245
year: extended_year,
246246
extended_year,
247+
related_gregorian: extended_year + YEAR_OFFSET + 1,
247248
ambiguity: types::YearAmbiguity::CenturyRequired,
248249
}
249250
}
@@ -544,4 +545,24 @@ mod tests {
544545
}
545546
}
546547
}
548+
549+
#[test]
550+
fn related_gregorian() {
551+
assert_eq!(
552+
Date::try_new_gregorian(2025, 3, 18)
553+
.unwrap()
554+
.to_calendar(Indian)
555+
.era_year()
556+
.related_gregorian,
557+
2025
558+
);
559+
assert_eq!(
560+
Date::try_new_gregorian(2025, 4, 18)
561+
.unwrap()
562+
.to_calendar(Indian)
563+
.era_year()
564+
.related_gregorian,
565+
2026
566+
);
567+
}
547568
}

components/calendar/src/cal/iso.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,18 @@ impl GregorianYears for IsoEra {
4141
}
4242
}
4343

44-
fn era_year_from_extended(&self, extended_year: i32, _month: u8, _day: u8) -> types::EraYear {
44+
fn era_year_from_extended(
45+
&self,
46+
extended_year: i32,
47+
related_gregorian: i32,
48+
_month: u8,
49+
_day: u8,
50+
) -> types::EraYear {
4551
types::EraYear {
4652
era_index: Some(0),
4753
era: tinystr!(16, "default"),
4854
year: extended_year,
55+
related_gregorian,
4956
extended_year,
5057
ambiguity: types::YearAmbiguity::Unambiguous,
5158
}

components/calendar/src/cal/japanese.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,13 @@ impl GregorianYears for &'_ Japanese {
222222
Ok(era_start.year + year - 1)
223223
}
224224

225-
fn era_year_from_extended(&self, year: i32, month: u8, day: u8) -> types::EraYear {
225+
fn era_year_from_extended(
226+
&self,
227+
year: i32,
228+
related_gregorian: i32,
229+
month: u8,
230+
day: u8,
231+
) -> types::EraYear {
226232
let date: EraStartDate = EraStartDate { year, month, day };
227233

228234
let (start, era) = if date >= MEIJI_START
@@ -255,7 +261,7 @@ impl GregorianYears for &'_ Japanese {
255261
return types::EraYear {
256262
// TODO: return era indices?
257263
era_index: None,
258-
..CeBce.era_year_from_extended(year, month, day)
264+
..CeBce.era_year_from_extended(year, related_gregorian, month, day)
259265
};
260266
}
261267
Ok(index) => data.get(index).unwrap(),
@@ -267,6 +273,7 @@ impl GregorianYears for &'_ Japanese {
267273
era,
268274
era_index: None,
269275
year: year - start.year + 1,
276+
related_gregorian,
270277
extended_year: year,
271278
ambiguity: types::YearAmbiguity::CenturyRequired,
272279
}

0 commit comments

Comments
 (0)