use std::fmt;
macro_rules! month {
($i:ident, $days:literal, $name:literal) => {
pub(crate) const $i: Month = Month {
name: $name,
days: $days,
common_offset: 0
};
};
($i:ident, $days:literal, $name:literal, $prev:ident) => {
pub(crate) const $i: Month = Month {
name: $name,
days: $days,
common_offset: $prev.common_offset + $prev.days as u16
};
};
}
month!(JAN, 31, "January");
month!(FEB, 28, "February", JAN);
month!(MAR, 31, "March", FEB);
month!(APR, 30, "April", MAR);
month!(MAY, 31, "May", APR);
month!(JUN, 30, "June", MAY);
month!(JUL, 31, "July", JUN);
month!(AUG, 31, "August", JUL);
month!(SEP, 30, "September", AUG);
month!(OCT, 31, "October", SEP);
month!(NOV, 30, "November", OCT);
month!(DEC, 31, "December", NOV);
pub(crate) const MONTHS: [Month; 12] = [
JAN,
FEB,
MAR,
APR,
MAY,
JUN,
JUL,
AUG,
SEP,
OCT,
NOV,
DEC
];
pub mod offset {
macro_rules! offset {
($m:ident) => {
pub(crate) const $m: u16 = super::$m.common_offset;
};
}
offset!(JAN);
offset!(FEB);
offset!(MAR);
offset!(APR);
offset!(MAY);
offset!(JUN);
offset!(JUL);
offset!(AUG);
offset!(SEP);
offset!(OCT);
offset!(NOV);
offset!(DEC);
}
#[derive(Clone, Copy)]
pub(crate) struct Month {
pub(crate) name: &'static str,
pub(crate) days: u8,
pub(crate) common_offset: u16
}
impl fmt::Display for Month {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.name)
}
}
#[test]
fn month() {
assert_eq!(DEC.common_offset, 365 - 31);
let mut prev = 365;
for m in MONTHS.iter().rev() {
assert_eq!(prev - m.days as u16, m.common_offset);
prev -= m.days as u16;
}
assert_eq!(prev, 0);
}