diff --git a/components/calendar/src/indian.rs b/components/calendar/src/indian.rs index a44ef1b53c1..478e7a8159d 100644 --- a/components/calendar/src/indian.rs +++ b/components/calendar/src/indian.rs @@ -308,6 +308,7 @@ impl DateTime { #[cfg(test)] mod tests { use super::*; + use crate::rata_die::RataDie; fn assert_roundtrip(y: i32, m: u8, d: u8, iso_y: i32, iso_m: u8, iso_d: u8) { let indian = Date::try_new_indian_date(y, m, d).expect("Indian date should construct successfully"); @@ -363,4 +364,205 @@ mod tests { assert_roundtrip(1942, 11, 7, 2021, 1, 27); assert_roundtrip(1941, 11, 7, 2020, 1, 27); } + + #[derive(Debug)] + struct TestCase { + iso_year: i32, + iso_month: u8, + iso_day: u8, + expected_year: i32, + expected_month: u32, + expected_day: u32, + } + + fn check_case(case: TestCase) { + let iso = Date::try_new_iso_date(case.iso_year, case.iso_month, case.iso_day).unwrap(); + let saka = iso.to_calendar(Indian); + assert_eq!( + saka.year().number, + case.expected_year, + "Year check failed for case: {case:?}" + ); + assert_eq!( + saka.month().ordinal, + case.expected_month, + "Month check failed for case: {case:?}" + ); + assert_eq!( + saka.day_of_month().0, + case.expected_day, + "Day check failed for case: {case:?}" + ); + } + + #[test] + fn test_cases_near_epoch_start() { + let cases = [ + TestCase { + iso_year: 79, + iso_month: 3, + iso_day: 23, + expected_year: 1, + expected_month: 1, + expected_day: 2, + }, + TestCase { + iso_year: 79, + iso_month: 3, + iso_day: 22, + expected_year: 1, + expected_month: 1, + expected_day: 1, + }, + TestCase { + iso_year: 79, + iso_month: 3, + iso_day: 21, + expected_year: 0, + expected_month: 12, + expected_day: 30, + }, + TestCase { + iso_year: 79, + iso_month: 3, + iso_day: 20, + expected_year: 0, + expected_month: 12, + expected_day: 29, + }, + TestCase { + iso_year: 78, + iso_month: 3, + iso_day: 21, + expected_year: -1, + expected_month: 12, + expected_day: 30, + }, + ]; + + for case in cases { + check_case(case); + } + } + + #[test] + fn test_cases_near_rd_zero() { + let cases = [ + TestCase { + iso_year: 1, + iso_month: 3, + iso_day: 22, + expected_year: -77, + expected_month: 1, + expected_day: 1, + }, + TestCase { + iso_year: 1, + iso_month: 3, + iso_day: 21, + expected_year: -78, + expected_month: 12, + expected_day: 30, + }, + TestCase { + iso_year: 1, + iso_month: 1, + iso_day: 1, + expected_year: -78, + expected_month: 10, + expected_day: 11, + }, + TestCase { + iso_year: 0, + iso_month: 3, + iso_day: 21, + expected_year: -78, + expected_month: 1, + expected_day: 1, + }, + TestCase { + iso_year: 0, + iso_month: 1, + iso_day: 1, + expected_year: -79, + expected_month: 10, + expected_day: 11, + }, + TestCase { + iso_year: -1, + iso_month: 3, + iso_day: 21, + expected_year: -80, + expected_month: 12, + expected_day: 30, + }, + ]; + + for case in cases { + check_case(case); + } + } + + #[test] + fn test_roundtrip_near_rd_zero() { + for i in -1000..=1000 { + let initial = RataDie::new(i); + let result = Iso::fixed_from_iso( + Iso::iso_from_fixed(initial) + .to_calendar(Indian) + .to_calendar(Iso) + .inner, + ); + assert_eq!( + initial, result, + "Roundtrip failed for initial: {initial:?}, result: {result:?}" + ); + } + } + + #[test] + fn test_roundtrip_near_epoch_start() { + // Epoch start: RD 28570 + for i in 27570..=29570 { + let initial = RataDie::new(i); + let result = Iso::fixed_from_iso( + Iso::iso_from_fixed(initial) + .to_calendar(Indian) + .to_calendar(Iso) + .inner, + ); + assert_eq!( + initial, result, + "Roundtrip failed for initial: {initial:?}, result: {result:?}" + ); + } + } + + #[test] + fn test_directionality_near_rd_zero() { + for i in -100..=100 { + for j in -100..=100 { + let rd_i = RataDie::new(i); + let rd_j = RataDie::new(j); + + let indian_i = Iso::iso_from_fixed(rd_i).to_calendar(Indian); + let indian_j = Iso::iso_from_fixed(rd_j).to_calendar(Indian); + + assert_eq!(i.cmp(&j), indian_i.cmp(&indian_j), "Directionality test failed for i: {i}, j: {j}, indian_i: {indian_i:?}, indian_j: {indian_j:?}"); + } + } + } + + #[test] + fn test_directionality_near_epoch_start() { + // Epoch start: RD 28570 + for i in 28470..=28670 { + for j in 28470..=28670 { + let indian_i = Iso::iso_from_fixed(RataDie::new(i)).to_calendar(Indian); + let indian_j = Iso::iso_from_fixed(RataDie::new(j)).to_calendar(Indian); + + assert_eq!(i.cmp(&j), indian_i.cmp(&indian_j), "Directionality test failed for i: {i}, j: {j}, indian_i: {indian_i:?}, indian_j: {indian_j:?}"); + } + } + } }