date_time_matrix/
weekday_and_hour.rs

1use core::iter::Iterator;
2
3#[cfg(feature = "with-chrono")]
4use chrono::{DateTime, NaiveDateTime, TimeZone};
5use hour::Hour;
6use weekday::Weekday;
7
8//
9#[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Debug, Copy, Clone)]
10pub struct WeekdayAndHour(pub Weekday, pub Hour);
11
12#[cfg(feature = "with-chrono")]
13impl From<NaiveDateTime> for WeekdayAndHour {
14    fn from(dt: NaiveDateTime) -> Self {
15        Self(Weekday::from(dt), Hour::from(dt))
16    }
17}
18
19#[cfg(feature = "with-chrono")]
20impl<Tz: TimeZone> From<DateTime<Tz>> for WeekdayAndHour {
21    fn from(dt: DateTime<Tz>) -> Self {
22        Self(Weekday::from(dt.clone()), Hour::from(dt))
23    }
24}
25
26//
27#[derive(Debug, Clone, Default)]
28pub struct WeekdayAndHourIterator {
29    curr: Option<WeekdayAndHour>,
30}
31
32impl WeekdayAndHourIterator {
33    pub fn new() -> Self {
34        Self::default()
35    }
36}
37
38impl Iterator for WeekdayAndHourIterator {
39    type Item = WeekdayAndHour;
40
41    fn next(&mut self) -> Option<Self::Item> {
42        let new = match &self.curr {
43            Some(v) => {
44                let WeekdayAndHour(w, h) = v;
45                match h.next() {
46                    Some(h) => Some(WeekdayAndHour(w.to_owned(), h)),
47                    None => w.next().map(|w| WeekdayAndHour(w, Hour::C0)),
48                }
49            }
50            None => Some(WeekdayAndHour(Weekday::first(), Hour::C0)),
51        };
52        self.curr = new.to_owned();
53        new
54    }
55}
56
57//
58#[derive(Debug, Clone, Default)]
59pub struct WeekdayFromSundayAndHourIterator {
60    curr: Option<WeekdayAndHour>,
61}
62
63impl WeekdayFromSundayAndHourIterator {
64    pub fn new() -> Self {
65        Self::default()
66    }
67}
68
69impl Iterator for WeekdayFromSundayAndHourIterator {
70    type Item = WeekdayAndHour;
71
72    fn next(&mut self) -> Option<Self::Item> {
73        let new = match &self.curr {
74            Some(v) => {
75                let WeekdayAndHour(w, h) = v;
76                match h.next() {
77                    Some(h) => Some(WeekdayAndHour(w.to_owned(), h)),
78                    None => w.next_from_sunday().map(|w| WeekdayAndHour(w, Hour::C0)),
79                }
80            }
81            None => Some(WeekdayAndHour(Weekday::first_from_sunday(), Hour::C0)),
82        };
83        self.curr = new.to_owned();
84        new
85    }
86}
87
88#[cfg(test)]
89mod tests {
90    use super::*;
91
92    #[cfg(feature = "with-chrono")]
93    #[test]
94    fn test_from_chrono() {
95        use chrono::Utc;
96
97        assert_eq!(
98            WeekdayAndHour::from("2021-08-01T00:00:00".parse::<NaiveDateTime>().unwrap()),
99            WeekdayAndHour(Weekday::Sun, Hour::C0)
100        );
101
102        assert_eq!(
103            WeekdayAndHour::from("2021-08-01T00:00:00Z".parse::<DateTime<Utc>>().unwrap()),
104            WeekdayAndHour(Weekday::Sun, Hour::C0)
105        );
106    }
107
108    #[test]
109    fn test_iter() {
110        assert_eq!(WeekdayAndHourIterator::new().count(), 7 * 24);
111
112        assert_eq!(
113            WeekdayAndHourIterator::new().next(),
114            Some(WeekdayAndHour(Weekday::Mon, Hour::C0))
115        );
116    }
117
118    #[test]
119    fn test_from_sunday_iter() {
120        assert_eq!(WeekdayFromSundayAndHourIterator::new().count(), 7 * 24);
121
122        assert_eq!(
123            WeekdayFromSundayAndHourIterator::new().next(),
124            Some(WeekdayAndHour(Weekday::Sun, Hour::C0))
125        );
126    }
127}