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
65 changes: 23 additions & 42 deletions components/calendar/src/cal/abstract_gregorian.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).

use crate::cal::iso::{IsoDateInner, IsoEra};
use crate::calendar_arithmetic::{
ArithmeticDate, ArithmeticDateBuilder, CalendarArithmetic, DateFieldsResolver,
};
use crate::calendar_arithmetic::{ArithmeticDate, ArithmeticDateBuilder, DateFieldsResolver};
use crate::error::{DateError, DateFromFieldsError, EcmaReferenceYearError, UnknownEraError};
use crate::options::DateFromFieldsOptions;
use crate::options::{DateAddOptions, DateDifferenceOptions};
Expand Down Expand Up @@ -43,7 +41,15 @@ impl ArithmeticDate<AbstractGregorian<IsoEra>> {
}
}

impl CalendarArithmetic for AbstractGregorian<IsoEra> {
pub(crate) const REFERENCE_YEAR: i32 = 1972;
#[cfg(test)]
pub(crate) const LAST_DAY_OF_REFERENCE_YEAR: RataDie =
calendrical_calculations::gregorian::day_before_year(REFERENCE_YEAR + 1);

impl<Y: GregorianYears> DateFieldsResolver for AbstractGregorian<Y> {
// Gregorian year
type YearInfo = i32;

fn days_in_provided_month(year: i32, month: u8) -> u8 {
// https://www.youtube.com/watch?v=J9KijLyP-yg&t=1394s
if month == 2 {
Expand All @@ -57,36 +63,6 @@ impl CalendarArithmetic for AbstractGregorian<IsoEra> {
12
}

fn provided_year_is_leap(year: i32) -> bool {
calendrical_calculations::gregorian::is_leap_year(year)
}

fn last_month_day_in_provided_year(_year: i32) -> (u8, u8) {
(12, 31)
}

fn days_in_provided_year(year: i32) -> u16 {
365 + calendrical_calculations::gregorian::is_leap_year(year) as u16
}

fn day_of_provided_year(year: Self::YearInfo, month: u8, day: u8) -> u16 {
calendrical_calculations::gregorian::days_before_month(year, month) + day as u16
}

fn date_from_provided_year_day(year: Self::YearInfo, year_day: u16) -> (u8, u8) {
calendrical_calculations::gregorian::year_day(year, year_day)
}
}

pub(crate) const REFERENCE_YEAR: i32 = 1972;
#[cfg(test)]
pub(crate) const LAST_DAY_OF_REFERENCE_YEAR: RataDie =
calendrical_calculations::gregorian::day_before_year(REFERENCE_YEAR + 1);

impl<Y: GregorianYears> DateFieldsResolver for AbstractGregorian<Y> {
// Gregorian year
type YearInfo = i32;

#[inline]
fn year_info_from_era(
&self,
Expand Down Expand Up @@ -130,8 +106,10 @@ impl<Y: GregorianYears> Calendar for AbstractGregorian<Y> {

fn from_rata_die(&self, date: RataDie) -> Self::DateInner {
let iso = match calendrical_calculations::gregorian::gregorian_from_fixed(date) {
Err(I32CastError::BelowMin) => ArithmeticDate::<AbstractGregorian<IsoEra>>::min_date(),
Err(I32CastError::AboveMax) => ArithmeticDate::max_date(),
Err(I32CastError::BelowMin) => {
ArithmeticDate::<AbstractGregorian<IsoEra>>::new_unchecked(i32::MIN, 1, 1)
}
Err(I32CastError::AboveMax) => ArithmeticDate::new_unchecked(i32::MAX, 12, 31),
Ok((year, month, day)) => ArithmeticDate::new_unchecked(year, month, day),
};

Expand Down Expand Up @@ -159,15 +137,15 @@ impl<Y: GregorianYears> Calendar for AbstractGregorian<Y> {
}

fn months_in_year(&self, date: &Self::DateInner) -> u8 {
date.months_in_year()
AbstractGregorian::<IsoEra>::months_in_provided_year(date.year)
}

fn days_in_year(&self, date: &Self::DateInner) -> u16 {
date.days_in_year()
365 + calendrical_calculations::gregorian::is_leap_year(date.year) as u16
}

fn days_in_month(&self, date: &Self::DateInner) -> u8 {
date.days_in_month()
AbstractGregorian::<IsoEra>::days_in_provided_month(date.year, date.month)
}

fn add(
Expand All @@ -194,19 +172,22 @@ impl<Y: GregorianYears> Calendar for AbstractGregorian<Y> {
}

fn is_in_leap_year(&self, date: &Self::DateInner) -> bool {
AbstractGregorian::<IsoEra>::provided_year_is_leap(date.year)
calendrical_calculations::gregorian::is_leap_year(date.year)
}

fn month(&self, date: &Self::DateInner) -> types::MonthInfo {
self.month_code_from_ordinal(&date.year, date.month)
}

fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth {
date.day_of_month()
types::DayOfMonth(date.day)
}

fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear {
date.day_of_year()
types::DayOfYear(
calendrical_calculations::gregorian::days_before_month(date.year, date.month)
+ date.day as u16,
)
}

fn debug_name(&self) -> &'static str {
Expand Down
53 changes: 13 additions & 40 deletions components/calendar/src/cal/chinese.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@

use crate::cal::iso::{Iso, IsoDateInner};
use crate::calendar_arithmetic::DateFieldsResolver;
use crate::calendar_arithmetic::{
ArithmeticDate, ArithmeticDateBuilder, CalendarArithmetic, ToExtendedYear,
};
use crate::calendar_arithmetic::{ArithmeticDate, ArithmeticDateBuilder, ToExtendedYear};
use crate::error::{
DateError, DateFromFieldsError, EcmaReferenceYearError, MonthCodeError, UnknownEraError,
};
Expand Down Expand Up @@ -524,7 +522,9 @@ impl LunarChinese<China> {
}
}

impl<R: Rules> CalendarArithmetic for LunarChinese<R> {
impl<R: Rules> DateFieldsResolver for LunarChinese<R> {
type YearInfo = LunarChineseYearData;

fn days_in_provided_month(year: LunarChineseYearData, month: u8) -> u8 {
year.days_in_month(month)
}
Expand All @@ -534,31 +534,6 @@ impl<R: Rules> CalendarArithmetic for LunarChinese<R> {
year.months_in_year()
}

/// Returns true if the given year is a leap year, and false if not.
fn provided_year_is_leap(year: LunarChineseYearData) -> bool {
year.leap_month().is_some()
}

/// Returns the (month, day) of the last day in a Chinese year (the day before Chinese New Year).
/// The last month in a year will always be 12 in a common year or 13 in a leap year. The day is
/// determined by finding the day immediately before the next new year and calculating the number
/// of days since the last new moon (beginning of the last month in the year).
fn last_month_day_in_provided_year(year: LunarChineseYearData) -> (u8, u8) {
if year.leap_month().is_some() {
(13, year.days_in_month(13))
} else {
(12, year.days_in_month(12))
}
}

fn days_in_provided_year(year: LunarChineseYearData) -> u16 {
year.days_in_year()
}
}

impl<R: Rules> DateFieldsResolver for LunarChinese<R> {
type YearInfo = LunarChineseYearData;

#[inline]
fn year_info_from_era(
&self,
Expand Down Expand Up @@ -632,13 +607,12 @@ impl<R: Rules> Calendar for LunarChinese<R> {
fn from_rata_die(&self, rd: RataDie) -> Self::DateInner {
let iso = Iso.from_rata_die(rd);
let y = {
let actual_iso = iso.0.extended_year();
let candidate = self.0.year_data(actual_iso);
let candidate = self.0.year_data(iso.0.year);

if rd >= candidate.new_year() {
candidate
} else {
self.0.year_data(actual_iso - 1)
self.0.year_data(iso.0.year - 1)
}
};
let (m, d) = y.md_from_rd(rd);
Expand All @@ -652,13 +626,12 @@ impl<R: Rules> Calendar for LunarChinese<R> {
fn from_iso(&self, iso: IsoDateInner) -> Self::DateInner {
let rd = Iso.to_rata_die(&iso);
let y = {
let actual_iso = iso.0.extended_year();
let candidate = self.0.year_data(actual_iso);
let candidate = self.0.year_data(iso.0.year);

if rd >= candidate.new_year() {
candidate
} else {
self.0.year_data(actual_iso - 1)
self.0.year_data(iso.0.year - 1)
}
};
let (m, d) = y.md_from_rd(rd);
Expand All @@ -672,11 +645,11 @@ impl<R: Rules> Calendar for LunarChinese<R> {
// Count the number of months in a given year, specified by providing a date
// from that year
fn days_in_year(&self, date: &Self::DateInner) -> u16 {
date.0.days_in_year()
date.0.year.days_in_year()
}

fn days_in_month(&self, date: &Self::DateInner) -> u8 {
date.0.days_in_month()
Self::days_in_provided_month(date.0.year, date.0.month)
}

fn add(
Expand Down Expand Up @@ -711,7 +684,7 @@ impl<R: Rules> Calendar for LunarChinese<R> {
}

fn is_in_leap_year(&self, date: &Self::DateInner) -> bool {
Self::provided_year_is_leap(date.0.year)
date.0.year.leap_month().is_some()
}

/// The calendar-specific month code represented by `date`;
Expand All @@ -724,7 +697,7 @@ impl<R: Rules> Calendar for LunarChinese<R> {

/// The calendar-specific day-of-month represented by `date`
fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth {
date.0.day_of_month()
types::DayOfMonth(date.0.day)
}

/// Information of the day of the year
Expand All @@ -737,7 +710,7 @@ impl<R: Rules> Calendar for LunarChinese<R> {
}

fn months_in_year(&self, date: &Self::DateInner) -> u8 {
date.0.months_in_year()
Self::months_in_provided_year(date.0.year)
}
}

Expand Down
55 changes: 18 additions & 37 deletions components/calendar/src/cal/coptic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).

use crate::cal::iso::{Iso, IsoDateInner};
use crate::calendar_arithmetic::{ArithmeticDate, CalendarArithmetic};
use crate::calendar_arithmetic::ArithmeticDate;
use crate::calendar_arithmetic::{ArithmeticDateBuilder, DateFieldsResolver};
use crate::error::{
DateError, DateFromFieldsError, EcmaReferenceYearError, MonthCodeError, UnknownEraError,
Expand Down Expand Up @@ -43,12 +43,14 @@ pub struct Coptic;
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)]
pub struct CopticDateInner(pub(crate) ArithmeticDate<Coptic>);

impl CalendarArithmetic for Coptic {
impl DateFieldsResolver for Coptic {
type YearInfo = i32;

fn days_in_provided_month(year: i32, month: u8) -> u8 {
if (1..=12).contains(&month) {
30
} else if month == 13 {
if Self::provided_year_is_leap(year) {
if year.rem_euclid(4) == 3 {
6
} else {
5
Expand All @@ -61,31 +63,6 @@ impl CalendarArithmetic for Coptic {
fn months_in_provided_year(_: i32) -> u8 {
13
}

fn provided_year_is_leap(year: i32) -> bool {
year.rem_euclid(4) == 3
}

fn last_month_day_in_provided_year(year: i32) -> (u8, u8) {
if Self::provided_year_is_leap(year) {
(13, 6)
} else {
(13, 5)
}
}

fn days_in_provided_year(year: i32) -> u16 {
if Self::provided_year_is_leap(year) {
366
} else {
365
}
}
}

impl DateFieldsResolver for Coptic {
type YearInfo = i32;

#[inline]
fn year_info_from_era(
&self,
Expand Down Expand Up @@ -166,8 +143,8 @@ impl Calendar for Coptic {
fn from_rata_die(&self, rd: RataDie) -> Self::DateInner {
CopticDateInner(
match calendrical_calculations::coptic::coptic_from_fixed(rd) {
Err(I32CastError::BelowMin) => ArithmeticDate::min_date(),
Err(I32CastError::AboveMax) => ArithmeticDate::max_date(),
Err(I32CastError::BelowMin) => ArithmeticDate::new_unchecked(i32::MIN, 1, 1),
Err(I32CastError::AboveMax) => ArithmeticDate::new_unchecked(i32::MAX, 13, 6),
Ok((year, month, day)) => ArithmeticDate::new_unchecked(year, month, day),
},
)
Expand All @@ -186,15 +163,19 @@ impl Calendar for Coptic {
}

fn months_in_year(&self, date: &Self::DateInner) -> u8 {
date.0.months_in_year()
Self::months_in_provided_year(date.0.year)
}

fn days_in_year(&self, date: &Self::DateInner) -> u16 {
date.0.days_in_year()
if self.is_in_leap_year(date) {
366
} else {
365
}
}

fn days_in_month(&self, date: &Self::DateInner) -> u8 {
date.0.days_in_month()
Self::days_in_provided_month(date.0.year, date.0.month)
}

fn add(
Expand All @@ -216,7 +197,7 @@ impl Calendar for Coptic {
}

fn year_info(&self, date: &Self::DateInner) -> Self::Year {
let year = date.0.extended_year();
let year = date.0.year;
types::EraYear {
era: tinystr!(16, "am"),
era_index: Some(0),
Expand All @@ -227,19 +208,19 @@ impl Calendar for Coptic {
}

fn is_in_leap_year(&self, date: &Self::DateInner) -> bool {
Self::provided_year_is_leap(date.0.year)
date.0.year.rem_euclid(4) == 3
}

fn month(&self, date: &Self::DateInner) -> types::MonthInfo {
self.month_code_from_ordinal(&date.0.year, date.0.month)
}

fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth {
date.0.day_of_month()
types::DayOfMonth(date.0.day)
}

fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear {
date.0.day_of_year()
types::DayOfYear(30 * (date.0.month as u16 - 1) + date.0.day as u16)
}

fn debug_name(&self) -> &'static str {
Expand Down
10 changes: 9 additions & 1 deletion components/calendar/src/cal/ethiopian.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ impl DateFieldsResolver for Ethiopian {
// Coptic year
type YearInfo = i32;

fn days_in_provided_month(year: Self::YearInfo, month: u8) -> u8 {
Coptic::days_in_provided_month(year, month)
}

fn months_in_provided_year(year: Self::YearInfo) -> u8 {
Coptic::months_in_provided_year(year)
}

#[inline]
fn year_info_from_era(
&self,
Expand Down Expand Up @@ -187,7 +195,7 @@ impl Calendar for Ethiopian {
}

fn year_info(&self, date: &Self::DateInner) -> Self::Year {
let coptic_year = date.0 .0.extended_year();
let coptic_year = date.0 .0.year;
let extended_year = if self.0 == EthiopianEraStyle::AmeteAlem {
coptic_year - AMETE_ALEM_OFFSET
} else {
Expand Down
Loading
Loading