//! This module contains types and implementations for the Indian national calendar. //! //! ```rust //! use icu::calendar::{indian::Indian, Date, DateTime}; //! //! // `Date` type //! let date_iso = Date::try_new_iso_date(1970, 1, 2) //! .expect("Failed to initialize ISO Date instance."); //! let date_indian = Date::new_from_iso(date_iso, Indian); //! //! // `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_indian = DateTime::new_from_iso(datetime_iso, Indian); //! //! // `Date` checks //! assert_eq!(date_indian.year().number, 1891); //! assert_eq!(date_indian.month().ordinal, 10); //! assert_eq!(date_indian.day_of_month().0, 12); //! //! // `DateTime` type //! assert_eq!(datetime_indian.date.year().number, 1891); //! assert_eq!(datetime_indian.date.month().ordinal, 10); //! assert_eq!(datetime_indian.date.day_of_month().0, 12); //! assert_eq!(datetime_indian.time.hour.number(), 13); //! assert_eq!(datetime_indian.time.minute.number(), 1); //! assert_eq!(datetime_indian.time.second.number(), 0); //! ```
usecrate::any_calendar::AnyCalendarKind; usecrate::calendar_arithmetic::{ArithmeticDate, CalendarArithmetic}; usecrate::iso::Iso; usecrate::{types, Calendar, CalendarError, Date, DateDuration, DateDurationUnit, DateTime, Time}; use tinystr::tinystr;
/// The Indian National Calendar (aka the Saka calendar) /// /// The [Indian National calendar] is a solar calendar used by the Indian government, with twelve months. /// /// This type can be used with [`Date`] or [`DateTime`] to represent dates in this calendar. /// /// [Indian National calendar]: https://en.wikipedia.org/wiki/Indian_national_calendar /// /// # Era codes /// /// This calendar has a single era: `"saka"`, with Saka 0 being 78 CE. Dates before this era use negative years. /// /// # 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 Indian;
/// The inner date type used for representing [`Date`]s of [`Indian`]. See [`Date`] and [`Indian`] for more details. #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] pubstruct IndianDateInner(ArithmeticDate<Indian>);
impl CalendarArithmetic for Indian { type YearInfo = ();
/// The Saka calendar starts on the 81st day of the Gregorian year (March 22 or 21) /// which is an 80 day offset. This number should be subtracted from Gregorian dates const DAY_OFFSET: u16 = 80; /// The Saka calendar is 78 years behind Gregorian. This number should be added to Gregorian dates const YEAR_OFFSET: i32 = 78;
impl Calendar for Indian { type DateInner = IndianDateInner; fn date_from_codes(
&self,
era: types::Era,
year: i32,
month_code: types::MonthCode,
day: u8,
) -> Result<Self::DateInner, CalendarError> { if era.0 != tinystr!(16, "saka") && era.0 != tinystr!(16, "indian") { return Err(CalendarError::UnknownEra(era.0, self.debug_name()));
}
// Algorithms directly implemented in icu_calendar since they're not from the book fn date_from_iso(&self, iso: Date<Iso>) -> IndianDateInner { // Get day number in year (1 indexed) let day_of_year_iso = Iso::day_of_year(*iso.inner()); // Convert to Saka year letmut year = iso.inner().0.year - YEAR_OFFSET; // This is in the previous Indian year let day_of_year_indian = if day_of_year_iso <= DAY_OFFSET {
year -= 1; let n_days = Self::days_in_provided_year(year, ());
// calculate day of year in previous year
n_days + day_of_year_iso - DAY_OFFSET
} else {
day_of_year_iso - DAY_OFFSET
};
IndianDateInner(ArithmeticDate::date_from_year_day(
year,
day_of_year_indian as u32,
))
}
// Algorithms directly implemented in icu_calendar since they're not from the book fn date_to_iso(&self, date: &Self::DateInner) -> Date<Iso> { let day_of_year_indian = date.0.day_of_year(); let days_in_year = date.0.days_in_year();
letmut year = date.0.year + YEAR_OFFSET; let day_of_year_iso = if day_of_year_indian + DAY_OFFSET >= days_in_year {
year += 1; // calculate day of year in next year
day_of_year_indian + DAY_OFFSET - days_in_year
} else {
day_of_year_indian + DAY_OFFSET
};
impl Date<Indian> { /// Construct new Indian Date, with year provided in the Śaka era. /// /// ```rust /// use icu::calendar::Date; /// /// let date_indian = Date::try_new_indian_date(1891, 10, 12) /// .expect("Failed to initialize Indian Date instance."); /// /// assert_eq!(date_indian.year().number, 1891); /// assert_eq!(date_indian.month().ordinal, 10); /// assert_eq!(date_indian.day_of_month().0, 12); /// ``` pubfn try_new_indian_date(
year: i32,
month: u8,
day: u8,
) -> Result<Date<Indian>, CalendarError> {
ArithmeticDate::new_from_ordinals(year, month, day)
.map(IndianDateInner)
.map(|inner| Date::from_raw(inner, Indian))
}
}
impl DateTime<Indian> { /// Construct a new Indian datetime from integers, with year provided in the Śaka era. /// /// ```rust /// use icu::calendar::DateTime; /// /// let datetime_indian = /// DateTime::try_new_indian_datetime(1891, 10, 12, 13, 1, 0) /// .expect("Failed to initialize Indian DateTime instance."); /// /// assert_eq!(datetime_indian.date.year().number, 1891); /// assert_eq!(datetime_indian.date.month().ordinal, 10); /// assert_eq!(datetime_indian.date.day_of_month().0, 12); /// assert_eq!(datetime_indian.time.hour.number(), 13); /// assert_eq!(datetime_indian.time.minute.number(), 1); /// assert_eq!(datetime_indian.time.second.number(), 0); /// ``` pubfn try_new_indian_datetime(
year: i32,
month: u8,
day: u8,
hour: u8,
minute: u8,
second: u8,
) -> Result<DateTime<Indian>, CalendarError> {
Ok(DateTime {
date: Date::try_new_indian_date(year, month, day)?,
time: Time::try_new(hour, minute, second, 0)?,
})
}
}
#[cfg(test)] mod tests { usesuper::*; use calendrical_calculations::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"); let iso = indian.to_iso();
assert_eq!(
iso.year().number,
iso_y, "{y}-{m}-{d}: ISO year did not match"
);
assert_eq!(
iso.month().ordinal as u8,
iso_m, "{y}-{m}-{d}: ISO month did not match"
);
assert_eq!(
iso.day_of_month().0as u8,
iso_d, "{y}-{m}-{d}: ISO day did not match"
);
let roundtrip = iso.to_calendar(Indian);
assert_eq!(
roundtrip.year().number,
indian.year().number, "{y}-{m}-{d}: roundtrip year did not match"
);
assert_eq!(
roundtrip.month().ordinal,
indian.month().ordinal, "{y}-{m}-{d}: roundtrip month did not match"
);
assert_eq!(
roundtrip.day_of_month(),
indian.day_of_month(), "{y}-{m}-{d}: roundtrip day did not match"
);
}
#[test] fn roundtrip_indian() { // Ultimately the day of the year will always be identical regardless of it // being a leap year or not // Test dates that occur after and before Chaitra 1 (March 22/21), in all years of // a four-year leap cycle, to ensure that all code paths are tested
assert_roundtrip(1944, 6, 7, 2022, 8, 29);
assert_roundtrip(1943, 6, 7, 2021, 8, 29);
assert_roundtrip(1942, 6, 7, 2020, 8, 29);
assert_roundtrip(1941, 6, 7, 2019, 8, 29);
assert_roundtrip(1944, 11, 7, 2023, 1, 27);
assert_roundtrip(1943, 11, 7, 2022, 1, 27);
assert_roundtrip(1942, 11, 7, 2021, 1, 27);
assert_roundtrip(1941, 11, 7, 2020, 1, 27);
}
#[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 in27570..=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 in28470..=28670 { for j in28470..=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:?}");
}
}
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-06-19)
¤
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.