//! This module contains types and implementations for the Republic of China calendar. //! //! ```rust //! use icu::calendar::{roc::Roc, Date, DateTime}; //! //! // `Date` type //! let date_iso = Date::try_new_iso_date(1970, 1, 2) //! .expect("Failed to initialize ISO Date instance."); //! let date_roc = Date::new_from_iso(date_iso, Roc); //! //! // `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_roc = DateTime::new_from_iso(datetime_iso, Roc); //! //! // `Date` checks //! assert_eq!(date_roc.year().number, 59); //! assert_eq!(date_roc.month().ordinal, 1); //! assert_eq!(date_roc.day_of_month().0, 2); //! //! // `DateTime` checks //! assert_eq!(datetime_roc.date.year().number, 59); //! assert_eq!(datetime_roc.date.month().ordinal, 1); //! assert_eq!(datetime_roc.date.day_of_month().0, 2); //! assert_eq!(datetime_roc.time.hour.number(), 13); //! assert_eq!(datetime_roc.time.minute.number(), 1); //! assert_eq!(datetime_roc.time.second.number(), 0); //! ```
usecrate::{
calendar_arithmetic::ArithmeticDate, iso::IsoDateInner, types, AnyCalendarKind, Calendar,
CalendarError, Date, DateTime, Iso, Time,
}; use calendrical_calculations::helpers::i64_to_saturated_i32; use tinystr::tinystr;
/// Year of the beginning of the Taiwanese (ROC/Minguo) calendar. /// 1912 ISO = ROC 1 const ROC_ERA_OFFSET: i32 = 1911;
/// The Republic of China (ROC) Calendar /// /// The [Republic of China calendar] is a solar calendar used in Taiwan and Penghu, as well as by overseas diaspora from /// those locations. Months and days are identical to the [`Gregorian`] calendar, while years are counted /// with 1912, the year of the establishment of the Republic of China, as year 1 of the ROC/Minguo/民国/民國 era. /// /// [Republic of China calendar]: https://en.wikipedia.org/wiki/Republic_of_China_calendar /// /// The Republic of China calendar should not be confused with the Chinese traditional lunar calendar /// (see [`Chinese`]). /// /// # Era codes /// /// This calendar supports two era codes: `"roc"`, corresponding to years in the 民國 (minguo) era (CE year 1912 and /// after), and `"roc-inverse"`, corresponding to years before the 民國 (minguo) era (CE year 1911 and before). /// /// /// # Month codes /// /// This calendar supports 12 solar month codes (`"M01" - "M12"`) /// /// [`Chinese`]: crate::chinese::Chinese /// [`Gregorian`]: crate::Gregorian #[derive(Copy, Clone, Debug, Default)] #[allow(clippy::exhaustive_structs)] // this type is stable pubstruct Roc;
/// The inner date type used for representing [`Date`]s of [`Roc`]. See [`Date`] and [`Roc`] for more info. #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] pubstruct RocDateInner(IsoDateInner);
impl Calendar for Roc { type DateInner = RocDateInner;
fn date_from_codes(
&self,
era: crate::types::Era,
year: i32,
month_code: crate::types::MonthCode,
day: u8,
) -> Result<Self::DateInner, crate::Error> { let year = if era.0 == tinystr!(16, "roc") { if year <= 0 { return Err(CalendarError::OutOfRange);
}
year + ROC_ERA_OFFSET
} elseif era.0 == tinystr!(16, "roc-inverse") { if year <= 0 { return Err(CalendarError::OutOfRange);
} 1 - year + ROC_ERA_OFFSET
} else { return Err(CalendarError::UnknownEra(era.0, self.debug_name()));
};
fn day_of_year_info(&self, date: &Self::DateInner) -> crate::types::DayOfYearInfo { let prev_year = date.0 .0.year.saturating_sub(1); let next_year = date.0 .0.year.saturating_add(1);
types::DayOfYearInfo {
day_of_year: Iso::day_of_year(date.0),
days_in_year: Iso::days_in_year_direct(date.0 .0.year),
prev_year: year_as_roc(prev_year as i64),
days_in_prev_year: Iso::days_in_year_direct(prev_year),
next_year: year_as_roc(next_year as i64),
}
}
/// The [`AnyCalendarKind`] corresponding to this calendar fn any_calendar_kind(&self) -> Option<AnyCalendarKind> {
Some(AnyCalendarKind::Roc)
}
}
impl Date<Roc> { /// Construct a new Republic of China calendar Date. /// /// Years are specified in the "roc" era. This function accepts an extended year in that era, so dates /// before Minguo are negative and year 0 is 1 Before Minguo. To specify dates using explicit era /// codes, use [`Roc::date_from_codes()`]. /// /// ```rust /// use icu::calendar::Date; /// use icu::calendar::gregorian::Gregorian; /// use tinystr::tinystr; /// /// // Create a new ROC Date /// let date_roc = Date::try_new_roc_date(1, 2, 3) /// .expect("Failed to initialize ROC Date instance."); /// /// assert_eq!(date_roc.year().era.0, tinystr!(16, "roc")); /// assert_eq!(date_roc.year().number, 1, "ROC year check failed!"); /// assert_eq!(date_roc.month().ordinal, 2, "ROC month check failed!"); /// assert_eq!(date_roc.day_of_month().0, 3, "ROC day of month check failed!"); /// /// // Convert to an equivalent Gregorian date /// let date_gregorian = date_roc.to_calendar(Gregorian); /// /// assert_eq!(date_gregorian.year().number, 1912, "Gregorian from ROC year check failed!"); /// assert_eq!(date_gregorian.month().ordinal, 2, "Gregorian from ROC month check failed!"); /// assert_eq!(date_gregorian.day_of_month().0, 3, "Gregorian from ROC day of month check failed!"); pubfn try_new_roc_date(year: i32, month: u8, day: u8) -> Result<Date<Roc>, CalendarError> { let iso_year = year.saturating_add(ROC_ERA_OFFSET);
Date::try_new_iso_date(iso_year, month, day).map(|d| Date::new_from_iso(d, Roc))
}
}
impl DateTime<Roc> { /// Construct a new Republic of China calendar datetime from integers. /// /// Years are specified in the "roc" era, Before Minguo dates are negative (year 0 is 1 Before Minguo) /// /// ```rust /// use icu::calendar::DateTime; /// use tinystr::tinystr; /// /// // Create a new ROC DateTime /// let datetime_roc = DateTime::try_new_roc_datetime(1, 2, 3, 13, 1, 0) /// .expect("Failed to initialize ROC DateTime instance."); /// /// assert_eq!(datetime_roc.date.year().era.0, tinystr!(16, "roc")); /// assert_eq!(datetime_roc.date.year().number, 1, "ROC year check failed!"); /// assert_eq!( /// datetime_roc.date.month().ordinal, /// 2, /// "ROC month check failed!" /// ); /// assert_eq!( /// datetime_roc.date.day_of_month().0, /// 3, /// "ROC day of month check failed!" /// ); /// assert_eq!(datetime_roc.time.hour.number(), 13); /// assert_eq!(datetime_roc.time.minute.number(), 1); /// assert_eq!(datetime_roc.time.second.number(), 0); /// ``` pubfn try_new_roc_datetime(
year: i32,
month: u8,
day: u8,
hour: u8,
minute: u8,
second: u8,
) -> Result<DateTime<Roc>, CalendarError> {
Ok(DateTime {
date: Date::try_new_roc_date(year, month, day)?,
time: Time::try_new(hour, minute, second, 0)?,
})
}
}
fn check_test_case(case: TestCase) { let iso_from_fixed = Iso::iso_from_fixed(case.fixed_date); let roc_from_fixed = Date::new_from_iso(iso_from_fixed, Roc);
assert_eq!(roc_from_fixed.year().number, case.expected_year, "Failed year check from fixed: {case:?}\nISO: {iso_from_fixed:?}\nROC: {roc_from_fixed:?}");
assert_eq!(roc_from_fixed.year().era, case.expected_era, "Failed era check from fixed: {case:?}\nISO: {iso_from_fixed:?}\nROC: {roc_from_fixed:?}");
assert_eq!(roc_from_fixed.month().ordinal, case.expected_month, "Failed month check from fixed: {case:?}\nISO: {iso_from_fixed:?}\nROC: {roc_from_fixed:?}");
assert_eq!(roc_from_fixed.day_of_month().0, case.expected_day, "Failed day_of_month check from fixed: {case:?}\nISO: {iso_from_fixed:?}\nROC: {roc_from_fixed:?}");
let iso_from_case = Date::try_new_iso_date(case.iso_year, case.iso_month, case.iso_day)
.expect("Failed to initialize ISO date for {case:?}"); let roc_from_case = Date::new_from_iso(iso_from_case, Roc);
assert_eq!(iso_from_fixed, iso_from_case, "ISO from fixed not equal to ISO generated from manually-input ymd\nCase: {case:?}\nFixed: {iso_from_fixed:?}\nManual: {iso_from_case:?}");
assert_eq!(roc_from_fixed, roc_from_case, "ROC date from fixed not equal to ROC generated from manually-input ymd\nCase: {case:?}\nFixed: {roc_from_fixed:?}\nManual: {roc_from_case:?}");
}
#[test] fn test_roc_current_era() { // Tests that the ROC calendar gives the correct expected day, month, and year for years >= 1912 // (years in the ROC/minguo era) // // Jan 1. 1912 CE = RD 697978
#[test] fn test_roc_directionality_near_epoch() { // Tests that for a large range of fixed dates near the beginning of the minguo era (CE 1912), // the comparison between those two fixed dates should be equal to the comparison between their // corresponding YMD. let rd_epoch_start = 697978; for i in (rd_epoch_start - 100)..=(rd_epoch_start + 100) { for j in (rd_epoch_start - 100)..=(rd_epoch_start + 100) { let iso_i = Iso::iso_from_fixed(RataDie::new(i)); let iso_j = Iso::iso_from_fixed(RataDie::new(j));
let roc_i = iso_i.to_calendar(Roc); let roc_j = iso_j.to_calendar(Roc);
assert_eq!(
i.cmp(&j),
iso_i.cmp(&iso_j), "ISO directionality inconsistent with directionality for i: {i}, j: {j}"
);
assert_eq!(
i.cmp(&j),
roc_i.cmp(&roc_j), "ROC directionality inconsistent with directionality for i: {i}, j: {j}"
);
}
}
}
#[test] fn test_roc_directionality_near_rd_zero() { // Same as `test_directionality_near_epoch`, but with a focus around RD 0 for i in -100..=100 { for j in -100..100 { let iso_i = Iso::iso_from_fixed(RataDie::new(i)); let iso_j = Iso::iso_from_fixed(RataDie::new(j));
let roc_i = iso_i.to_calendar(Roc); let roc_j = iso_j.to_calendar(Roc);
assert_eq!(
i.cmp(&j),
iso_i.cmp(&iso_j), "ISO directionality inconsistent with directionality for i: {i}, j: {j}"
);
assert_eq!(
i.cmp(&j),
roc_i.cmp(&roc_j), "ROC directionality inconsistent with directionality for i: {i}, j: {j}"
);
}
}
}
}
Messung V0.5 in Prozent
¤ 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.0.10Bemerkung:
(vorverarbeitet am 2026-06-18)
¤
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.