use calendrical_calculations::rata_die::RataDie;
use crate::cal::iso::IsoDateInner;
use crate::error::{DateAddError, DateError, DateFromFieldsError, DateNewError};
use crate::options::DateFromFieldsOptions;
use crate::options::{DateAddOptions, DateDifferenceOptions};
use crate::types::{self, Month, YearInput};
use crate::Iso;
use core::fmt;
#[cfg(doc)]
use crate::Date;
pub trait Calendar: crate::cal::scaffold::UnstableSealed {
type DateInner: Eq + Copy + PartialOrd + fmt::Debug;
type Year: fmt::Debug + Into<types::YearInfo>;
type DateCompatibilityError: fmt::Debug;
#[expect(clippy::wrong_self_convention)]
#[deprecated(since = "2.2.0", note = "use `new_date`")]
fn from_codes(
&self,
era: Option<&str>,
year: i32,
month_code: types::MonthCode,
day: u8,
) -> Result<Self::DateInner, DateError> {
let input_year = match era {
Some(e) => YearInput::EraYear(e, year),
None => year.into(),
};
let month = match Month::try_from_utf8(month_code.0.as_bytes()) {
Ok(m) => m,
Err(_) => return Err(DateError::UnknownMonthCode(month_code)),
};
let result = self.new_date(input_year, month, day);
match result {
Ok(date) => Ok(date),
Err(codes_error) => Err(match codes_error {
DateNewError::InvalidDay { max } => DateError::Range {
field: "day",
value: day as i32,
min: 1,
max: max as i32,
},
DateNewError::MonthNotInCalendar | DateNewError::MonthNotInYear => {
DateError::UnknownMonthCode(month_code)
}
DateNewError::InvalidEra => DateError::UnknownEra,
DateNewError::InvalidYear => DateError::Range {
field: "year",
value: year,
min: -9999,
max: 9999,
},
}),
}
}
fn new_date(
&self,
year: YearInput,
month: Month,
day: u8,
) -> Result<Self::DateInner, DateNewError>;
#[expect(clippy::wrong_self_convention)]
fn from_fields(
&self,
fields: types::DateFields,
options: DateFromFieldsOptions,
) -> Result<Self::DateInner, DateFromFieldsError>;
fn has_cheap_iso_conversion(&self) -> bool;
#[expect(clippy::wrong_self_convention)]
fn from_iso(&self, iso: IsoDateInner) -> Self::DateInner {
self.from_rata_die(Iso.to_rata_die(&iso))
}
fn to_iso(&self, date: &Self::DateInner) -> IsoDateInner {
Iso.from_rata_die(self.to_rata_die(date))
}
#[expect(clippy::wrong_self_convention)]
fn from_rata_die(&self, rd: RataDie) -> Self::DateInner;
fn to_rata_die(&self, date: &Self::DateInner) -> RataDie;
fn months_in_year(&self, date: &Self::DateInner) -> u8;
fn days_in_year(&self, date: &Self::DateInner) -> u16;
fn days_in_month(&self, date: &Self::DateInner) -> u8;
fn is_in_leap_year(&self, date: &Self::DateInner) -> bool;
fn year_info(&self, date: &Self::DateInner) -> Self::Year;
fn extended_year(&self, date: &Self::DateInner) -> i32 {
self.year_info(date).into().extended_year()
}
fn month(&self, date: &Self::DateInner) -> types::MonthInfo;
fn day_of_month(&self, date: &Self::DateInner) -> types::DayOfMonth;
fn day_of_year(&self, date: &Self::DateInner) -> types::DayOfYear;
fn add(
&self,
date: &Self::DateInner,
duration: types::DateDuration,
options: DateAddOptions,
) -> Result<Self::DateInner, DateAddError>;
fn until(
&self,
date1: &Self::DateInner,
date2: &Self::DateInner,
options: DateDifferenceOptions,
) -> types::DateDuration;
fn check_date_compatibility(&self, other: &Self) -> Result<(), Self::DateCompatibilityError>;
fn calendar_algorithm(&self) -> Option<crate::preferences::CalendarAlgorithm>;
fn debug_name(&self) -> &'static str;
}