1use time::Date;23pub struct WeekdayIterator {4 start: time::Date,5 off: i8, // offset in weeks6}78impl Iterator for WeekdayIterator {9 type Item = time::Date;1011 fn next(&mut self) -> Option<Self::Item> {12 if self.off == 0 {13 self.off += 1;14 return Some(self.start);15 }1617 let dur = time::Duration::weeks(self.off as i64);18 let day = self.start.checked_add(dur)?;19 if day.month() != self.start.month() {20 None21 } else {22 self.off += 1;23 Some(day)24 }25 }26}2728fn iterator(year: i32, month: time::Month, wday: time::Weekday) -> Option<WeekdayIterator> {29 let mut day = Date::from_calendar_date(year, month, 1).ok()?;3031 // Find first matching weekday in given month.32 while day.weekday() != wday {33 if day.month() != month {34 return None;35 }3637 day = day.next_day()?;38 }3940 Some(WeekdayIterator { start: day, off: 0 })41}4243pub fn filter(year: i32, month: time::Month, wday: time::Weekday) -> Option<Vec<time::Date>> {44 iterator(year, month, wday).map(|it| it.collect())45}4647////////////////////////////////////////////////////////////////////////4849#[cfg(test)]50mod tests {51 use super::*;52 use time::macros::date;5354 #[test]55 fn filter_five() {56 let mondays = filter(2023, time::Month::January, time::Weekday::Monday).unwrap();57 assert_eq!(58 mondays,59 vec![60 date!(2023 - 01 - 02),61 date!(2023 - 01 - 09),62 date!(2023 - 01 - 16),63 date!(2023 - 01 - 23),64 date!(2023 - 01 - 30),65 ]66 );67 }6869 #[test]70 fn filter_four() {71 let mondays = filter(2023, time::Month::February, time::Weekday::Monday).unwrap();72 assert_eq!(73 mondays,74 vec![75 date!(2023 - 02 - 06),76 date!(2023 - 02 - 13),77 date!(2023 - 02 - 20),78 date!(2023 - 02 - 27),79 ]80 );81 }82}