datetime_string/
datetime.rs1use core::fmt;
4
5#[derive(Debug, Clone, Copy)]
7pub(crate) enum DateError {
8 MonthOutOfRange,
10 MdayOutOfRange,
12}
13
14impl fmt::Display for DateError {
15 #[inline]
16 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17 let msg = match self {
18 Self::MonthOutOfRange => "Month is out of range",
19 Self::MdayOutOfRange => "Day of month is out of range",
20 };
21 f.write_str(msg)
22 }
23}
24
25#[inline]
27pub(crate) fn is_leap_year(year: u16) -> bool {
28 (year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0))
29}
30
31pub(crate) fn validate_ym0d(year: u16, month0: u8, mday: u8) -> Result<(), DateError> {
35 const NORMAL_MDAY_MAX: [u8; 12] = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
37
38 if month0 >= 12 {
39 return Err(DateError::MonthOutOfRange);
40 }
41
42 if mday != 29 {
45 return if mday <= NORMAL_MDAY_MAX[month0 as usize] {
46 Ok(())
47 } else {
48 Err(DateError::MdayOutOfRange)
49 };
50 }
51
52 let mday_max = if is_leap_year(year) { 29 } else { 28 };
54
55 if mday <= mday_max {
56 Ok(())
57 } else {
58 Err(DateError::MdayOutOfRange)
59 }
60}
61
62#[inline]
66pub(crate) fn validate_ym1d(year: u16, month1: u8, mday: u8) -> Result<(), DateError> {
67 validate_ym0d(year, month1.wrapping_sub(1), mday)
68}