use chrono::{Datelike, Duration, Months, NaiveDate, Weekday}; #[derive(Debug)] pub struct CalendarRow { pub begin: NaiveDate, pub end: NaiveDate, } pub enum RowDay { InRange(NaiveDate), NotInRange(NaiveDate), } impl RowDay { pub fn new(row: &CalendarRow, day: NaiveDate) -> RowDay { if day >= row.begin && day < row.end { RowDay::InRange(day) } else { RowDay::NotInRange(day) } } pub fn day(self) -> NaiveDate { match self { Self::InRange(day) => day, Self::NotInRange(day) => day, } } } /// A row in the calendar. /// /// The row is always aligned to a week, i.e. the first /// day of the row is the first day of the week (for now always Monday) impl CalendarRow { /// A row that spans the month containing the given day pub fn for_month(day: NaiveDate) -> CalendarRow { let begin = day.with_day0(0).unwrap(); CalendarRow { begin, end: begin + Months::new(1), } } /// A row that spans the week containing the given day pub fn for_week(day: NaiveDate) -> CalendarRow { let begin = day.week(Weekday::Mon).first_day(); CalendarRow { begin, end: begin + Duration::weeks(1), } } /// Get the day for the given column of the row pub fn date_for_col(self: &Self, col: i64) -> RowDay { RowDay::new( self, self.begin.week(Weekday::Mon).first_day() + Duration::days(col), ) } pub fn num_days(&self) -> i64 { (self.end - self.begin).num_days() } }