use core::fmt;
#[derive(Debug, Clone, Copy)]
pub(crate) enum DateError {
MonthOutOfRange,
MdayOutOfRange,
}
impl fmt::Display for DateError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let msg = match self {
Self::MonthOutOfRange => "Month is out of range",
Self::MdayOutOfRange => "Day of month is out of range",
};
f.write_str(msg)
}
}
#[inline]
pub(crate) fn is_leap_year(year: u16) -> bool {
(year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0))
}
pub(crate) fn validate_ym0d(year: u16, month0: u8, mday: u8) -> Result<(), DateError> {
const NORMAL_MDAY_MAX: [u8; 12] = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
if month0 >= 12 {
return Err(DateError::MonthOutOfRange);
}
if mday != 29 {
return if mday <= NORMAL_MDAY_MAX[month0 as usize] {
Ok(())
} else {
Err(DateError::MdayOutOfRange)
};
}
let mday_max = if is_leap_year(year) { 29 } else { 28 };
if mday <= mday_max {
Ok(())
} else {
Err(DateError::MdayOutOfRange)
}
}
#[inline]
pub(crate) fn validate_ym1d(year: u16, month1: u8, mday: u8) -> Result<(), DateError> {
validate_ym0d(year, month1.wrapping_sub(1), mday)
}