use crate::types::MonthCode;
use displaydoc::Display;
#[derive(Debug, Copy, Clone, PartialEq, Display)]
#[non_exhaustive]
pub enum DateError {
#[displaydoc("The {field} = {value} argument is out of range {min}..={max}")]
Range {
field: &'static str,
value: i32,
min: i32,
max: i32,
},
#[displaydoc("Unknown era")]
UnknownEra,
#[displaydoc("Unknown month code {0:?}")]
UnknownMonthCode(MonthCode),
}
impl core::error::Error for DateError {}
#[derive(Debug, Copy, Clone, PartialEq, Display)]
#[non_exhaustive]
pub enum LunisolarDateError {
#[displaydoc("Invalid day for month, max is {max}")]
InvalidDay {
max: u8,
},
#[displaydoc("The specified month exists in this calendar, but not for this year")]
MonthNotInYear,
#[displaydoc("The specified month does not exist in this calendar")]
MonthNotInCalendar,
#[displaydoc("Invalid year")]
InvalidYear,
}
impl core::error::Error for LunisolarDateError {}
#[derive(Debug, Copy, Clone, PartialEq, Display)]
#[non_exhaustive]
pub enum DateFromFieldsError {
#[displaydoc("Invalid day for month, max is {max}")]
InvalidDay {
max: u8,
},
#[displaydoc("Invalid ordinal month for year, max is {max}")]
InvalidOrdinalMonth {
max: u8,
},
#[displaydoc("Invalid month code syntax")]
MonthCodeInvalidSyntax,
#[displaydoc("The specified month does not exist in this calendar")]
MonthNotInCalendar,
#[displaydoc("The specified month exists in this calendar, but not for this year")]
MonthNotInYear,
#[displaydoc("Unknown era or invalid syntax")]
InvalidEra,
#[displaydoc("Inconsistent year")]
InconsistentYear,
#[displaydoc("Inconsistent month")]
InconsistentMonth,
#[displaydoc("Too many fields")]
TooManyFields,
#[displaydoc("Not enough fields")]
NotEnoughFields,
#[displaydoc("Result out of range")]
Overflow,
}
impl core::error::Error for DateFromFieldsError {}
#[derive(Debug, Copy, Clone, PartialEq, Display)]
#[non_exhaustive]
pub enum DateAddError {
#[displaydoc("Invalid day for month, max is {max}")]
InvalidDay {
max: u8,
},
#[displaydoc("The specified month exists in this calendar, but not for this year")]
MonthNotInYear,
#[displaydoc("Result out of range")]
Overflow,
}
impl core::error::Error for DateAddError {}
#[derive(Clone, Copy, PartialEq, Debug, Display)]
#[displaydoc("Attempted to interact two `Date`s with different calendars")]
#[allow(
clippy::exhaustive_structs,
reason = "This is the only possible error with multi-calendar operations"
)]
pub struct MismatchedCalendarError;
impl core::error::Error for MismatchedCalendarError {}
#[derive(Debug, Copy, Clone, PartialEq, Display)]
#[non_exhaustive]
pub enum DateNewError {
#[displaydoc("Invalid day for month, max is {max}")]
InvalidDay {
max: u8,
},
#[displaydoc("The specified month does not exist in this calendar")]
MonthNotInCalendar,
#[displaydoc("The specified month exists in this calendar, but not for this year")]
MonthNotInYear,
#[displaydoc("Unknown era or invalid syntax")]
InvalidEra,
#[displaydoc("Invalid year, must be within -9999..=9999")]
InvalidYear,
}
impl core::error::Error for DateNewError {}
impl From<UnknownEraError> for DateNewError {
fn from(_: UnknownEraError) -> Self {
Self::InvalidEra
}
}
pub(crate) struct UnknownEraError;
impl From<UnknownEraError> for DateError {
#[inline]
fn from(_value: UnknownEraError) -> Self {
DateError::UnknownEra
}
}
impl From<UnknownEraError> for DateFromFieldsError {
#[inline]
fn from(_value: UnknownEraError) -> Self {
DateFromFieldsError::InvalidEra
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum MonthCodeParseError {
InvalidSyntax,
}
impl From<MonthCodeParseError> for DateFromFieldsError {
#[inline]
fn from(value: MonthCodeParseError) -> Self {
match value {
MonthCodeParseError::InvalidSyntax => DateFromFieldsError::MonthCodeInvalidSyntax,
}
}
}
#[derive(Debug, PartialEq)]
pub(crate) enum MonthError {
NotInCalendar,
NotInYear,
}
impl From<MonthError> for DateFromFieldsError {
#[inline]
fn from(value: MonthError) -> Self {
match value {
MonthError::NotInCalendar => DateFromFieldsError::MonthNotInCalendar,
MonthError::NotInYear => DateFromFieldsError::MonthNotInYear,
}
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[non_exhaustive]
pub enum DateDurationParseError {
InvalidStructure,
TimeNotSupported,
MissingValue,
DuplicateUnit,
NumberOverflow,
PlusNotAllowed,
}
mod inner {
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[allow(missing_docs)] #[non_exhaustive]
pub enum EcmaReferenceYearError {
Unimplemented,
MonthNotInCalendar,
UseRegularIfConstrain,
}
}
#[cfg(feature = "unstable")]
pub use inner::EcmaReferenceYearError;
#[cfg(not(feature = "unstable"))]
pub(crate) use inner::EcmaReferenceYearError;
impl From<EcmaReferenceYearError> for DateFromFieldsError {
#[inline]
fn from(value: EcmaReferenceYearError) -> Self {
match value {
EcmaReferenceYearError::Unimplemented => DateFromFieldsError::NotEnoughFields,
EcmaReferenceYearError::MonthNotInCalendar => DateFromFieldsError::MonthNotInCalendar,
EcmaReferenceYearError::UseRegularIfConstrain => DateFromFieldsError::MonthNotInYear,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Display)]
#[displaydoc("The {field} = {value} argument is out of range {min}..={max}")]
#[allow(clippy::exhaustive_structs)]
pub struct RangeError {
pub field: &'static str,
pub value: i32,
pub min: i32,
pub max: i32,
}
impl core::error::Error for RangeError {}
impl From<RangeError> for DateError {
#[inline]
fn from(value: RangeError) -> Self {
let RangeError {
field,
value,
min,
max,
} = value;
DateError::Range {
field,
value,
min,
max,
}
}
}
pub(crate) fn range_check<T: Ord + Into<i32> + Copy>(
value: T,
field: &'static str,
bounds: core::ops::RangeInclusive<T>,
) -> Result<T, RangeError> {
if !bounds.contains(&value) {
return Err(RangeError {
field,
value: value.into(),
min: (*bounds.start()).into(),
max: (*bounds.end()).into(),
});
}
Ok(value)
}