Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 3 additions & 23 deletions components/calendar/src/cal/abstract_gregorian.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::options::DateFromFieldsOptions;
use crate::options::{DateAddOptions, DateDifferenceOptions};
use crate::preferences::CalendarAlgorithm;
use crate::types::EraYear;
use crate::{types, Calendar, RangeError};
use crate::{types, Calendar};
use calendrical_calculations::rata_die::RataDie;

#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
Expand All @@ -31,27 +31,6 @@ pub(crate) trait GregorianYears: Clone + core::fmt::Debug {
fn debug_name(&self) -> &'static str;
}

impl ArithmeticDate<AbstractGregorian<IsoEra>> {
pub(crate) fn new_gregorian<Y: GregorianYears>(
year: i32,
month: u8,
day: u8,
) -> Result<Self, RangeError> {
ArithmeticDate::try_from_ymd(year + Y::EXTENDED_YEAR_OFFSET, month, day).map_err(|e| {
if e.field == "year" {
RangeError {
value: e.value - Y::EXTENDED_YEAR_OFFSET,
min: e.min - Y::EXTENDED_YEAR_OFFSET,
max: e.max - Y::EXTENDED_YEAR_OFFSET,
..e
}
} else {
e
}
})
}
}

pub(crate) const REFERENCE_YEAR: i32 = 1972;
#[cfg(test)]
pub(crate) const LAST_DAY_OF_REFERENCE_YEAR: RataDie =
Expand Down Expand Up @@ -108,7 +87,8 @@ impl<Y: GregorianYears> Calendar for AbstractGregorian<Y> {
month_code: types::MonthCode,
day: u8,
) -> Result<Self::DateInner, DateError> {
ArithmeticDate::from_codes(era, year, month_code, day, self).map(ArithmeticDate::cast)
ArithmeticDate::from_era_year_month_code_day(era, year, month_code, day, self)
.map(ArithmeticDate::cast)
}

#[cfg(feature = "unstable")]
Expand Down
9 changes: 6 additions & 3 deletions components/calendar/src/cal/buddhist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).

use crate::cal::abstract_gregorian::AbstractGregorian;
use crate::error::UnknownEraError;
use crate::preferences::CalendarAlgorithm;
use crate::{
Expand Down Expand Up @@ -74,9 +75,10 @@ impl GregorianYears for BuddhistEra {
}

impl Date<Buddhist> {
/// Construct a new Buddhist Date.
/// Construct a new Buddhist [`Date`].
///
/// Years are specified as BE years.
/// Years are arithmetic, meaning there is a year 0 preceded by negative years, with a
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: This sentence doesn't read correctly for me. The word "arithmetic" is a noun by default, so "years are arithmetic" doesn't make sense. If using "arithmetic" as an adjective, please don't use it in a position in the sentence where it could be interpreted as a noun.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't write this

/// Years are arithmetic, meaning there is a year 0. Zero and negative years are in BC, with year 0 = 1 BC

/// valid range of `-1,000,000..=1,000,000`.
///
/// ```rust
/// use icu::calendar::Date;
Expand All @@ -89,7 +91,8 @@ impl Date<Buddhist> {
/// assert_eq!(date_buddhist.day_of_month().0, 2);
/// ```
pub fn try_new_buddhist(year: i32, month: u8, day: u8) -> Result<Date<Buddhist>, RangeError> {
ArithmeticDate::new_gregorian::<BuddhistEra>(year, month, day)
ArithmeticDate::from_year_month_day(year, month, day, &AbstractGregorian(BuddhistEra))
.map(ArithmeticDate::cast)
.map(BuddhistDateInner)
.map(|i| Date::from_raw(i, Buddhist))
}
Expand Down
10 changes: 7 additions & 3 deletions components/calendar/src/cal/coptic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ impl Calendar for Coptic {
month_code: types::MonthCode,
day: u8,
) -> Result<Self::DateInner, DateError> {
ArithmeticDate::from_codes(era, year, month_code, day, self).map(CopticDateInner)
ArithmeticDate::from_era_year_month_code_day(era, year, month_code, day, self)
.map(CopticDateInner)
}

#[cfg(feature = "unstable")]
Expand Down Expand Up @@ -234,7 +235,10 @@ impl Calendar for Coptic {
}

impl Date<Coptic> {
/// Construct new Coptic Date.
/// Construct new Coptic [`Date`].
///
/// Years are arithmetic, meaning there is a year 0 preceded by negative years, with a
/// valid range of `-1,000,000..=1,000,000`.
///
/// ```rust
/// use icu::calendar::Date;
Expand All @@ -247,7 +251,7 @@ impl Date<Coptic> {
/// assert_eq!(date_coptic.day_of_month().0, 6);
/// ```
pub fn try_new_coptic(year: i32, month: u8, day: u8) -> Result<Date<Coptic>, RangeError> {
ArithmeticDate::try_from_ymd(year, month, day)
ArithmeticDate::from_year_month_day(year, month, day, &Coptic)
.map(CopticDateInner)
.map(|inner| Date::from_raw(inner, Coptic))
}
Expand Down
41 changes: 36 additions & 5 deletions components/calendar/src/cal/east_asian_traditional.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,9 @@ impl Rules for Korea {
impl<A: AsCalendar<Calendar = KoreanTraditional>> Date<A> {
/// This method uses an ordinal month, which is probably not what you want.
///
/// Years are arithmetic, meaning there is a year 0 preceded by negative years, with a
/// valid range of `-1,000,000..=1,000,000`.
///
/// Use [`Date::try_new_from_codes`]
#[deprecated(since = "2.1.0", note = "use `Date::try_new_from_codes`")]
pub fn try_new_dangi_with_calendar(
Expand All @@ -482,10 +485,11 @@ impl<A: AsCalendar<Calendar = KoreanTraditional>> Date<A> {
day: u8,
calendar: A,
) -> Result<Date<A>, DateError> {
ArithmeticDate::try_from_ymd(
calendar.as_calendar().0.year(related_iso_year),
ArithmeticDate::from_year_month_day(
related_iso_year,
ordinal_month,
day,
calendar.as_calendar(),
)
.map(ChineseDateInner)
.map(|inner| Date::from_raw(inner, calendar))
Expand Down Expand Up @@ -595,6 +599,7 @@ impl<R: Rules> DateFieldsResolver for EastAsianTraditional<R> {

#[inline]
fn year_info_from_extended(&self, extended_year: i32) -> Self::YearInfo {
debug_assert!(crate::calendar_arithmetic::VALID_YEAR_RANGE.contains(&extended_year));
self.0.year(extended_year)
}

Expand Down Expand Up @@ -667,7 +672,8 @@ impl<R: Rules> Calendar for EastAsianTraditional<R> {
month_code: types::MonthCode,
day: u8,
) -> Result<Self::DateInner, DateError> {
ArithmeticDate::from_codes(era, year, month_code, day, self).map(ChineseDateInner)
ArithmeticDate::from_era_year_month_code_day(era, year, month_code, day, self)
.map(ChineseDateInner)
}

#[cfg(feature = "unstable")]
Expand Down Expand Up @@ -783,6 +789,9 @@ impl<R: Rules> Calendar for EastAsianTraditional<R> {
impl<A: AsCalendar<Calendar = ChineseTraditional>> Date<A> {
/// This method uses an ordinal month, which is probably not what you want.
///
/// Years are arithmetic, meaning there is a year 0 preceded by negative years, with a
/// valid range of `-1,000,000..=1,000,000`.
///
/// Use [`Date::try_new_from_codes`]
#[deprecated(since = "2.1.0", note = "use `Date::try_new_from_codes`")]
pub fn try_new_chinese_with_calendar(
Expand All @@ -791,10 +800,11 @@ impl<A: AsCalendar<Calendar = ChineseTraditional>> Date<A> {
day: u8,
calendar: A,
) -> Result<Date<A>, DateError> {
ArithmeticDate::try_from_ymd(
calendar.as_calendar().0.year(related_iso_year),
ArithmeticDate::from_year_month_day(
related_iso_year,
ordinal_month,
day,
calendar.as_calendar(),
)
.map(ChineseDateInner)
.map(|inner| Date::from_raw(inner, calendar))
Expand Down Expand Up @@ -1039,6 +1049,27 @@ impl PackedEastAsianTraditionalYearData {
}
}

// Precalculates Chinese years, significant performance improvement for big tests
#[cfg(test)]
#[derive(Debug, Clone)]
pub(crate) struct EastAsianTraditionalYears(Vec<EastAsianTraditionalYear>);

#[cfg(test)]
impl EastAsianTraditionalYears {
pub fn new<R: Rules>(r: R) -> Self {
Self((-1100000..=1100000).map(|i| r.year(i)).collect())
}
}

#[cfg(test)]
impl crate::cal::scaffold::UnstableSealed for EastAsianTraditionalYears {}
#[cfg(test)]
impl Rules for EastAsianTraditionalYears {
fn year(&self, related_iso: i32) -> EastAsianTraditionalYear {
self.0[(related_iso + 1100000) as usize]
}
}

#[cfg(test)]
mod test {
use super::*;
Expand Down
13 changes: 9 additions & 4 deletions components/calendar/src/cal/ethiopian.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ impl Calendar for Ethiopian {
month_code: types::MonthCode,
day: u8,
) -> Result<Self::DateInner, DateError> {
ArithmeticDate::from_codes(era, year, month_code, day, self)
ArithmeticDate::from_era_year_month_code_day(era, year, month_code, day, self)
.map(ArithmeticDate::cast)
.map(CopticDateInner)
.map(EthiopianDateInner)
Expand Down Expand Up @@ -272,7 +272,12 @@ impl Ethiopian {
}

impl Date<Ethiopian> {
/// Construct new Ethiopian Date.
/// Construct new Ethiopian [`Date`].
///
/// Years are arithmetic, meaning there is a year 0 preceded by negative years, with a
/// valid range of `-1,000,000..=1,000,000`.
///
/// Years are interpreted according to the provided `era_style`.
///
/// ```rust
/// use icu::calendar::cal::EthiopianEraStyle;
Expand All @@ -292,8 +297,8 @@ impl Date<Ethiopian> {
month: u8,
day: u8,
) -> Result<Date<Ethiopian>, RangeError> {
let year = Ethiopian(era_style).year_info_from_extended(year);
ArithmeticDate::try_from_ymd(year, month, day)
ArithmeticDate::from_year_month_day(year, month, day, &Ethiopian(era_style))
.map(ArithmeticDate::cast)
.map(CopticDateInner)
.map(EthiopianDateInner)
.map(|inner| Date::from_raw(inner, Ethiopian(era_style)))
Expand Down
12 changes: 8 additions & 4 deletions components/calendar/src/cal/gregorian.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).

use crate::cal::abstract_gregorian::{impl_with_abstract_gregorian, GregorianYears};
use crate::cal::abstract_gregorian::{
impl_with_abstract_gregorian, AbstractGregorian, GregorianYears,
};
use crate::calendar_arithmetic::ArithmeticDate;
use crate::error::UnknownEraError;
use crate::preferences::CalendarAlgorithm;
Expand Down Expand Up @@ -118,9 +120,10 @@ impl GregorianYears for CeBce {
pub struct Gregorian;

impl Date<Gregorian> {
/// Construct a new Gregorian Date.
/// Construct a new Gregorian [`Date`].
///
/// Years are specified as ISO years.
/// Years are arithmetic, meaning there is a year 0 preceded by negative years, with a
/// valid range of `-1,000,000..=1,000,000`.
///
/// ```rust
/// use icu::calendar::Date;
Expand All @@ -134,7 +137,8 @@ impl Date<Gregorian> {
/// assert_eq!(date_gregorian.day_of_month().0, 2);
/// ```
pub fn try_new_gregorian(year: i32, month: u8, day: u8) -> Result<Date<Gregorian>, RangeError> {
ArithmeticDate::new_gregorian::<CeBce>(year, month, day)
ArithmeticDate::from_year_month_day(year, month, day, &AbstractGregorian(CeBce))
.map(ArithmeticDate::cast)
.map(GregorianDateInner)
.map(|i| Date::from_raw(i, Gregorian))
}
Expand Down
10 changes: 6 additions & 4 deletions components/calendar/src/cal/hebrew.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,8 @@ impl Calendar for Hebrew {
month_code: types::MonthCode,
day: u8,
) -> Result<Self::DateInner, DateError> {
ArithmeticDate::from_codes(era, year, month_code, day, self).map(HebrewDateInner)
ArithmeticDate::from_era_year_month_code_day(era, year, month_code, day, self)
.map(HebrewDateInner)
}

#[cfg(feature = "unstable")]
Expand Down Expand Up @@ -346,16 +347,17 @@ impl Calendar for Hebrew {
impl Date<Hebrew> {
/// This method uses an ordinal month, which is probably not what you want.
///
/// Years are arithmetic, meaning there is a year 0 preceded by negative years, with a
/// valid range of `-1,000,000..=1,000,000`.
///
/// Use [`Date::try_new_from_codes`]
#[deprecated(since = "2.1.0", note = "use `Date::try_new_from_codes`")]
pub fn try_new_hebrew(
year: i32,
ordinal_month: u8,
day: u8,
) -> Result<Date<Hebrew>, RangeError> {
let year = HebrewYear::compute(year);

ArithmeticDate::try_from_ymd(year, ordinal_month, day)
ArithmeticDate::from_year_month_day(year, ordinal_month, day, &Hebrew)
.map(HebrewDateInner)
.map(|inner| Date::from_raw(inner, Hebrew))
}
Expand Down
17 changes: 10 additions & 7 deletions components/calendar/src/cal/hijri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -888,6 +888,7 @@ impl<R: Rules> DateFieldsResolver for Hijri<R> {

#[inline]
fn year_info_from_extended(&self, extended_year: i32) -> Self::YearInfo {
debug_assert!(crate::calendar_arithmetic::VALID_YEAR_RANGE.contains(&extended_year));
self.0.year(extended_year)
}

Expand Down Expand Up @@ -916,7 +917,8 @@ impl<R: Rules> Calendar for Hijri<R> {
month_code: types::MonthCode,
day: u8,
) -> Result<Self::DateInner, DateError> {
ArithmeticDate::from_codes(era, year, month_code, day, self).map(HijriDateInner)
ArithmeticDate::from_era_year_month_code_day(era, year, month_code, day, self)
.map(HijriDateInner)
}

#[cfg(feature = "unstable")]
Expand Down Expand Up @@ -1028,7 +1030,10 @@ impl<R: Rules> Calendar for Hijri<R> {
}

impl<A: AsCalendar<Calendar = Hijri<R>>, R: Rules> Date<A> {
/// Construct new Hijri Date.
/// Construct new Hijri [`Date`].
///
/// Years are arithmetic, meaning there is a year 0 preceded by negative years, with a
/// valid range of `-1,000,000..=1,000,000`.
///
/// ```rust
/// use icu::calendar::cal::Hijri;
Expand All @@ -1049,11 +1054,9 @@ impl<A: AsCalendar<Calendar = Hijri<R>>, R: Rules> Date<A> {
day: u8,
calendar: A,
) -> Result<Self, RangeError> {
let y = calendar.as_calendar().0.year(year);
Ok(Date::from_raw(
HijriDateInner(ArithmeticDate::try_from_ymd(y, month, day)?),
calendar,
))
ArithmeticDate::from_year_month_day(year, month, day, calendar.as_calendar())
.map(HijriDateInner)
.map(|inner| Date::from_raw(inner, calendar))
}
}

Expand Down
10 changes: 7 additions & 3 deletions components/calendar/src/cal/indian.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ impl Calendar for Indian {
month_code: types::MonthCode,
day: u8,
) -> Result<Self::DateInner, DateError> {
ArithmeticDate::from_codes(era, year, month_code, day, self).map(IndianDateInner)
ArithmeticDate::from_era_year_month_code_day(era, year, month_code, day, self)
.map(IndianDateInner)
}

#[cfg(feature = "unstable")]
Expand Down Expand Up @@ -283,7 +284,10 @@ impl Indian {
}

impl Date<Indian> {
/// Construct new Indian Date, with year provided in the Śaka era.
/// Construct new Indian [`Date`].
///
/// Years are arithmetic, meaning there is a year 0 preceded by negative years, with a
/// valid range of `-1,000,000..=1,000,000`.
///
/// ```rust
/// use icu::calendar::Date;
Expand All @@ -296,7 +300,7 @@ impl Date<Indian> {
/// assert_eq!(date_indian.day_of_month().0, 12);
/// ```
pub fn try_new_indian(year: i32, month: u8, day: u8) -> Result<Date<Indian>, RangeError> {
ArithmeticDate::try_from_ymd(year, month, day)
ArithmeticDate::from_year_month_day(year, month, day, &Indian)
.map(IndianDateInner)
.map(|inner| Date::from_raw(inner, Indian))
}
Expand Down
Loading