// This file is part of ICU4X. For terms of use, please see the file // called LICENSE at the top level of the ICU4X source tree // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). use icu_calendar::*; const MAGNITUDE: i32 = 1_000_000; // Check rd -> date -> iso -> date -> rd for whole range #[test] #[ignore] // takes about 200 seconds in release-with-assertions fn check_round_trip() { fn test(cal: C) { let cal = Ref(&cal); let low = Date::try_new_iso(-MAGNITUDE, 1, 1).unwrap().to_rata_die(); let high = Date::try_new_iso(MAGNITUDE, 12, 31).unwrap().to_rata_die(); let mut prev = Date::from_rata_die(low, cal); let mut curr = low + 1; while curr <= high { let date = Date::from_rata_die(curr, cal); assert!(prev < date); let rd = date.to_rata_die(); assert_eq!(rd, curr, "{}", cal.as_calendar().debug_name()); let date2 = Date::new_from_iso(date.to_iso(), cal); assert_eq!(date, date2, "{:?}", cal.as_calendar().debug_name()); prev = date; curr += 1; } } for_each_calendar!(test); } #[test] #[ignore] // takes about 90 seconds in release-with-assertions fn check_from_fields() { fn test(cal: C) { let cal = Ref(&cal); let codes = (1..19) .flat_map(|i| { [ types::MonthCode::new_normal(i).unwrap(), types::MonthCode::new_leap(i).unwrap(), ] .into_iter() }) .collect::>(); for year in -MAGNITUDE..=MAGNITUDE { if year % 50000 == 0 { println!("{} {year:?}", cal.as_calendar().debug_name()); } for overflow in [options::Overflow::Constrain, options::Overflow::Reject] { let mut options = options::DateFromFieldsOptions::default(); options.overflow = Some(overflow); for mut fields in codes .iter() .map(|m| { let mut fields = types::DateFields::default(); fields.month_code = Some(m.0.as_bytes()); fields }) .chain((1..20).map(|m| { let mut fields = types::DateFields::default(); fields.ordinal_month = Some(m); fields })) { for day in 1..50 { fields.extended_year = Some(year); fields.day = Some(day); let _ = Date::try_from_fields(fields, options, Ref(&cal)); } } } } } for_each_calendar!(test); } macro_rules! for_each_calendar { ($f:ident) => { [ || { $f(cal::Buddhist); println!("Buddhist done"); }, || { $f(cal::east_asian_traditional::EastAsianTraditional( EastAsianTraditionalYears::new(cal::east_asian_traditional::China::default()), )); println!("Chinese done"); }, || { $f(cal::Coptic); println!("Coptic done"); }, || { $f(cal::east_asian_traditional::EastAsianTraditional( EastAsianTraditionalYears::new(cal::east_asian_traditional::Korea::default()), )); println!("Korean done"); }, || { $f(cal::Ethiopian::new()); println!("Ethiopian done"); }, || { $f(cal::Ethiopian::new_with_era_style( cal::EthiopianEraStyle::AmeteAlem, )); println!("Ethiopian (Amete Alem) done"); }, || { $f(cal::Gregorian); println!("Gregorian done"); }, || { $f(cal::Hebrew::new()); println!("Hebrew done"); }, || { $f(cal::Hijri::new_tabular( cal::hijri::TabularAlgorithmLeapYears::TypeII, cal::hijri::TabularAlgorithmEpoch::Friday, )); println!("Hijri (tabular) done"); }, || { $f(cal::Hijri::new_tabular( cal::hijri::TabularAlgorithmLeapYears::TypeII, cal::hijri::TabularAlgorithmEpoch::Thursday, )); println!("Hijri (astronomical) done"); }, || { $f(cal::Hijri::new_umm_al_qura()); println!("Hijri (UAQ) done"); }, || { $f(cal::Indian::new()); println!("Indian done"); }, || { $f(cal::Iso::new()); println!("Iso done"); }, || { $f(cal::Julian::new()); println!("Julian done"); }, || { $f(cal::Japanese::new()); println!("Japanese done"); }, || { $f(cal::JapaneseExtended::new()); println!("JapaneseExtended done"); }, || { $f(cal::Persian::new()); println!("Persian done"); }, || { $f(cal::Roc); println!("Roc done"); }, ] .map(std::thread::spawn) .into_iter() .for_each(|h| h.join().unwrap()); }; } use for_each_calendar; // Precalculates Chinese years, significant performance improvement #[derive(Debug, Clone)] struct EastAsianTraditionalYears(Vec); impl EastAsianTraditionalYears { fn new(r: R) -> Self { Self( ((-MAGNITUDE - 1)..=MAGNITUDE) .map(|i| r.year_data(i)) .collect(), ) } } impl cal::scaffold::UnstableSealed for EastAsianTraditionalYears {} impl cal::east_asian_traditional::Rules for EastAsianTraditionalYears { fn year_data( &self, related_iso: i32, ) -> cal::east_asian_traditional::EastAsianTraditionalYearData { self.0[(related_iso + MAGNITUDE + 1) as usize] } }