//! The international fixed calendar is a 13-month calendar with each month //! containing exactly 28 days. There is an extra day at the end of the year //! called the year day. //! //! In leap-years there is an extra day inserted at the end of June called the //! leap day. It is directly after the fourth week of june and is given to june, //! so it becomes June 29th. The day after June 29th starts the new month, Sol, //! with Sol 1. //! //! [Wikipedia: International Fixed Calendar][wp-ifc] //! [wp-ifc]: https://en.wikipedia.org/wiki/International_Fixed_Calendar use time::Date as TimeDate; const MONTHS: [[&str; 2]; 13] = [ ["January", "Jan"], ["February", "Feb"], ["March", "Mar"], ["April", "Apr"], ["May", "May"], ["June", "Jun"], ["Sol", "Sol"], ["July", "Jul"], ["August", "Aug"], ["September", "Sep"], ["October", "Oct"], ["November", "Nov"], ["December", "Dec"], ]; pub struct Calendar { pub year: usize, pub ordinal: usize, } impl Calendar { pub fn from_year(year: usize) -> Self { Self { year, ordinal: 0 } } pub fn from_time_date(date: TimeDate) -> Self { let year = date.year() as usize; let ord = date.ordinal() as usize; Self { year, ordinal: ord } } } pub struct Date { pub year: u32, pub month: u8, pub day: u8, } impl Date { pub fn from_time_date(date: TimeDate) -> Self { let year = date.year() as u32; let ord = date.ordinal(); if !year_leaps(year) || ord <= 168 { // not a leap year path // also the "leap year but before the leap-day" path Self { year, month: (ord / 28) as u8, day: (ord % 28) as u8, } } else if ord == 169 { Self { year, month: 6, day: 29, } } else { todo!() } } pub fn is_leap(&self) -> bool { year_leaps(self.year) } } /// Whether or not a year is a leap year fn year_leaps(year: u32) -> bool { let four = year % 4 == 0; let hundreds = year % 100 == 0; let fourhund = year % 400 == 0; // leap if: // - four AND NOT hundred // - four AND hundred AND fourhund // `fourhund` here checks `hundreds` by virtue of 100 being a multiple of 400 four && (!hundreds || fourhund) } mod test { use crate::ifc::year_leaps; #[test] fn leap_years() { // the examples given by wikipedia assert!(year_leaps(2000)); assert!(!year_leaps(1700)); assert!(!year_leaps(1800)); assert!(!year_leaps(1900)); // testing the four rule assert!(year_leaps(2024)); } }