//! This module contains types and implementations for the Julian calendar. //! //! ```rust //! use icu::calendar::{julian::Julian, Date, DateTime}; //! //! // `Date` type //! let date_iso = Date::try_new_iso_date(1970, 1, 2) //! .expect("Failed to initialize ISO Date instance."); //! let date_julian = Date::new_from_iso(date_iso, Julian); //! //! // `DateTime` type //! let datetime_iso = DateTime::try_new_iso_datetime(1970, 1, 2, 13, 1, 0) //! .expect("Failed to initialize ISO DateTime instance."); //! let datetime_julian = DateTime::new_from_iso(datetime_iso, Julian); //! //! // `Date` checks //! assert_eq!(date_julian.year().number, 1969); //! assert_eq!(date_julian.month().ordinal, 12); //! assert_eq!(date_julian.day_of_month().0, 20); //! //! // `DateTime` type //! assert_eq!(datetime_julian.date.year().number, 1969); //! assert_eq!(datetime_julian.date.month().ordinal, 12); //! assert_eq!(datetime_julian.date.day_of_month().0, 20); //! assert_eq!(datetime_julian.time.hour.number(), 13); //! assert_eq!(datetime_julian.time.minute.number(), 1); //! assert_eq!(datetime_julian.time.second.number(), 0); //! ```
usecrate::any_calendar::AnyCalendarKind; usecrate::calendar_arithmetic::{ArithmeticDate, CalendarArithmetic}; usecrate::gregorian::year_as_gregorian; usecrate::iso::Iso; usecrate::{types, Calendar, CalendarError, Date, DateDuration, DateDurationUnit, DateTime, Time}; use calendrical_calculations::helpers::I32CastError; use calendrical_calculations::rata_die::RataDie; use tinystr::tinystr;
/// The [Julian Calendar] /// /// The [Julian calendar] is a solar calendar that was used commonly historically, with twelve months. /// /// This type can be used with [`Date`] or [`DateTime`] to represent dates in this calendar. /// /// [Julian calendar]: https://en.wikipedia.org/wiki/Julian_calendar /// /// # Era codes /// /// This calendar supports two era codes: `"bce"`, and `"ce"`, corresponding to the BCE/BC and CE/AD eras /// /// # Month codes /// /// This calendar supports 12 solar month codes (`"M01" - "M12"`) #[derive(Copy, Clone, Debug, Hash, Default, Eq, PartialEq, PartialOrd, Ord)] #[allow(clippy::exhaustive_structs)] // this type is stable pubstruct Julian;
/// The inner date type used for representing [`Date`]s of [`Julian`]. See [`Date`] and [`Julian`] for more details. #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] // The inner date type used for representing Date<Julian> pubstruct JulianDateInner(pub(crate) ArithmeticDate<Julian>);
impl CalendarArithmetic for Julian { type YearInfo = ();
/// The calendar-specific year represented by `date` /// Julian has the same era scheme as Gregorian fn year(&self, date: &Self::DateInner) -> types::FormattableYear {
year_as_gregorian(date.0.year)
}
impl Julian { /// Construct a new Julian Calendar pubfn new() -> Self { Self
}
// "Fixed" is a day count representation of calendars staring from Jan 1st of year 1 of the Georgian Calendar. pub(crate) constfn fixed_from_julian(date: ArithmeticDate<Julian>) -> RataDie {
calendrical_calculations::julian::fixed_from_julian(date.year, date.month, date.day)
}
/// Convenience function so we can call days_in_year without /// needing to construct a full ArithmeticDate fn days_in_year_direct(year: i32) -> u16 { if Julian::is_leap_year(year, ()) { 366
} else { 365
}
}
impl Date<Julian> { /// Construct new Julian Date. /// /// Years are arithmetic, meaning there is a year 0. Zero and negative years are in BC, with year 0 = 1 BC /// /// ```rust /// use icu::calendar::Date; /// /// let date_julian = Date::try_new_julian_date(1969, 12, 20) /// .expect("Failed to initialize Julian Date instance."); /// /// assert_eq!(date_julian.year().number, 1969); /// assert_eq!(date_julian.month().ordinal, 12); /// assert_eq!(date_julian.day_of_month().0, 20); /// ``` pubfn try_new_julian_date(
year: i32,
month: u8,
day: u8,
) -> Result<Date<Julian>, CalendarError> {
ArithmeticDate::new_from_ordinals(year, month, day)
.map(JulianDateInner)
.map(|inner| Date::from_raw(inner, Julian))
}
}
impl DateTime<Julian> { /// Construct a new Julian datetime from integers. /// /// Years are arithmetic, meaning there is a year 0. Zero and negative years are in BC, with year 0 = 1 BC /// /// ```rust /// use icu::calendar::DateTime; /// /// let datetime_julian = /// DateTime::try_new_julian_datetime(1969, 12, 20, 13, 1, 0) /// .expect("Failed to initialize Julian DateTime instance."); /// /// assert_eq!(datetime_julian.date.year().number, 1969); /// assert_eq!(datetime_julian.date.month().ordinal, 12); /// assert_eq!(datetime_julian.date.day_of_month().0, 20); /// assert_eq!(datetime_julian.time.hour.number(), 13); /// assert_eq!(datetime_julian.time.minute.number(), 1); /// assert_eq!(datetime_julian.time.second.number(), 0); /// ``` pubfn try_new_julian_datetime(
year: i32,
month: u8,
day: u8,
hour: u8,
minute: u8,
second: u8,
) -> Result<DateTime<Julian>, CalendarError> {
Ok(DateTime {
date: Date::try_new_julian_date(year, month, day)?,
time: Time::try_new(hour, minute, second, 0)?,
})
}
}
#[cfg(test)] mod test { usesuper::*; use types::Era;
#[test] fn test_day_iso_to_julian() { // March 1st 200 is same on both calendars let iso_date = Date::try_new_iso_date(200, 3, 1).unwrap(); let julian_date = Julian.date_from_iso(iso_date);
assert_eq!(julian_date.0.year, 200);
assert_eq!(julian_date.0.month, 3);
assert_eq!(julian_date.0.day, 1);
// Feb 28th, 200 (iso) = Feb 29th, 200 (julian) let iso_date = Date::try_new_iso_date(200, 2, 28).unwrap(); let julian_date = Julian.date_from_iso(iso_date);
assert_eq!(julian_date.0.year, 200);
assert_eq!(julian_date.0.month, 2);
assert_eq!(julian_date.0.day, 29);
// March 1st 400 (iso) = Feb 29th, 400 (julian) let iso_date = Date::try_new_iso_date(400, 3, 1).unwrap(); let julian_date = Julian.date_from_iso(iso_date);
assert_eq!(julian_date.0.year, 400);
assert_eq!(julian_date.0.month, 2);
assert_eq!(julian_date.0.day, 29);
// Jan 1st, 2022 (iso) = Dec 19, 2021 (julian) let iso_date = Date::try_new_iso_date(2022, 1, 1).unwrap(); let julian_date = Julian.date_from_iso(iso_date);
assert_eq!(julian_date.0.year, 2021);
assert_eq!(julian_date.0.month, 12);
assert_eq!(julian_date.0.day, 19);
}
#[test] fn test_day_julian_to_iso() { // March 1st 200 is same on both calendars let julian_date = Date::try_new_julian_date(200, 3, 1).unwrap(); let iso_date = Julian.date_to_iso(julian_date.inner()); let iso_expected_date = Date::try_new_iso_date(200, 3, 1).unwrap();
assert_eq!(iso_date, iso_expected_date);
// Feb 28th, 200 (iso) = Feb 29th, 200 (julian) let julian_date = Date::try_new_julian_date(200, 2, 29).unwrap(); let iso_date = Julian.date_to_iso(julian_date.inner()); let iso_expected_date = Date::try_new_iso_date(200, 2, 28).unwrap();
assert_eq!(iso_date, iso_expected_date);
// March 1st 400 (iso) = Feb 29th, 400 (julian) let julian_date = Date::try_new_julian_date(400, 2, 29).unwrap(); let iso_date = Julian.date_to_iso(julian_date.inner()); let iso_expected_date = Date::try_new_iso_date(400, 3, 1).unwrap();
assert_eq!(iso_date, iso_expected_date);
// Jan 1st, 2022 (iso) = Dec 19, 2021 (julian) let julian_date = Date::try_new_julian_date(2021, 12, 19).unwrap(); let iso_date = Julian.date_to_iso(julian_date.inner()); let iso_expected_date = Date::try_new_iso_date(2022, 1, 1).unwrap();
assert_eq!(iso_date, iso_expected_date);
// March 1st, 2022 (iso) = Feb 16, 2022 (julian) let julian_date = Date::try_new_julian_date(2022, 2, 16).unwrap(); let iso_date = Julian.date_to_iso(julian_date.inner()); let iso_expected_date = Date::try_new_iso_date(2022, 3, 1).unwrap();
assert_eq!(iso_date, iso_expected_date);
}
#[test] fn test_roundtrip_negative() { // https://github.com/unicode-org/icu4x/issues/2254 let iso_date = Date::try_new_iso_date(-1000, 3, 3).unwrap(); let julian = iso_date.to_calendar(Julian::new()); let recovered_iso = julian.to_iso();
assert_eq!(iso_date, recovered_iso);
}
#[test] fn test_julian_near_era_change() { // Tests that the Julian calendar gives the correct expected // day, month, and year for positive years (CE)
for case in cases { let iso_from_fixed: Date<Iso> = Iso::iso_from_fixed(RataDie::new(case.fixed_date)); let julian_from_fixed: Date<Julian> = Date::new_from_iso(iso_from_fixed, Julian);
assert_eq!(julian_from_fixed.year().number, case.expected_year, "Failed year check from fixed: {case:?}\nISO: {iso_from_fixed:?}\nJulian: {julian_from_fixed:?}");
assert_eq!(julian_from_fixed.year().era, case.expected_era, "Failed era check from fixed: {case:?}\nISO: {iso_from_fixed:?}\nJulian: {julian_from_fixed:?}");
assert_eq!(julian_from_fixed.month().ordinal, case.expected_month, "Failed month check from fixed: {case:?}\nISO: {iso_from_fixed:?}\nJulian: {julian_from_fixed:?}");
assert_eq!(julian_from_fixed.day_of_month().0, case.expected_day, "Failed day check from fixed: {case:?}\nISO: {iso_from_fixed:?}\nJulian: {julian_from_fixed:?}");
let iso_date_man: Date<Iso> =
Date::try_new_iso_date(case.iso_year, case.iso_month, case.iso_day)
.expect("Failed to initialize ISO date for {case:?}"); let julian_date_man: Date<Julian> = Date::new_from_iso(iso_date_man, Julian);
assert_eq!(iso_from_fixed, iso_date_man, "ISO from fixed not equal to ISO generated from manually-input ymd\nCase: {case:?}\nFixed: {iso_from_fixed:?}\nMan: {iso_date_man:?}");
assert_eq!(julian_from_fixed, julian_date_man, "Julian from fixed not equal to Julian generated from manually-input ymd\nCase: {case:?}\nFixed: {julian_from_fixed:?}\nMan: {julian_date_man:?}");
}
}
#[test] fn test_julian_fixed_date_conversion() { // Tests that converting from fixed date to Julian then // back to fixed date yields the same fixed date for i in -10000..=10000 { let fixed = RataDie::new(i); let julian = Julian::julian_from_fixed(fixed); let new_fixed = Julian::fixed_from_julian(julian.0);
assert_eq!(fixed, new_fixed);
}
}
#[test] fn test_julian_directionality() { // Tests that for a large range of fixed dates, if a fixed date // is less than another, the corresponding YMD should also be less // than the other, without exception. for i in -100..=100 { for j in -100..=100 { let julian_i = Julian::julian_from_fixed(RataDie::new(i)).0; let julian_j = Julian::julian_from_fixed(RataDie::new(j)).0;
assert_eq!(
i.cmp(&j),
julian_i.cmp(&julian_j), "Julian directionality inconsistent with directionality for i: {i}, j: {j}"
);
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.