date_range/
iter.rs

1use core::{
2    iter::{DoubleEndedIterator, IntoIterator, Iterator},
3    mem,
4};
5
6use chrono::{Duration, NaiveDate};
7
8use crate::DateRange;
9
10#[derive(Debug, Copy, Clone, PartialEq)]
11pub struct DateRangeIterator {
12    since: NaiveDate,
13    until: NaiveDate,
14}
15
16// https://stackoverflow.com/questions/41679239/loop-over-date-range
17impl Iterator for DateRangeIterator {
18    type Item = NaiveDate;
19    fn next(&mut self) -> Option<Self::Item> {
20        if self.since <= self.until {
21            let next_front = self.since + Duration::days(1);
22            Some(mem::replace(&mut self.since, next_front))
23        } else {
24            None
25        }
26    }
27}
28impl DoubleEndedIterator for DateRangeIterator {
29    fn next_back(&mut self) -> Option<Self::Item> {
30        if self.since <= self.until {
31            let next_back = self.until - Duration::days(1);
32            Some(mem::replace(&mut self.until, next_back))
33        } else {
34            None
35        }
36    }
37}
38
39impl IntoIterator for DateRange {
40    type Item = NaiveDate;
41
42    type IntoIter = DateRangeIterator;
43
44    fn into_iter(self) -> Self::IntoIter {
45        DateRangeIterator {
46            since: self.since(),
47            until: self.until(),
48        }
49    }
50}
51impl IntoIterator for &DateRange {
52    type Item = NaiveDate;
53
54    type IntoIter = DateRangeIterator;
55
56    fn into_iter(self) -> Self::IntoIter {
57        DateRangeIterator {
58            since: self.since(),
59            until: self.until(),
60        }
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67
68    #[test]
69    fn simple() {
70        assert_eq!(
71            DateRange::new("2021-08-01".parse().unwrap(), "2021-08-05".parse().unwrap())
72                .unwrap()
73                .into_iter()
74                .collect::<Vec<_>>(),
75            vec![
76                "2021-08-01".parse().unwrap(),
77                "2021-08-02".parse().unwrap(),
78                "2021-08-03".parse().unwrap(),
79                "2021-08-04".parse().unwrap(),
80                "2021-08-05".parse().unwrap(),
81            ]
82        );
83
84        let date_range =
85            &DateRange::new("2021-08-01".parse().unwrap(), "2021-08-05".parse().unwrap()).unwrap();
86        assert_eq!(
87            date_range.into_iter().rev().collect::<Vec<_>>(),
88            vec![
89                "2021-08-05".parse().unwrap(),
90                "2021-08-04".parse().unwrap(),
91                "2021-08-03".parse().unwrap(),
92                "2021-08-02".parse().unwrap(),
93                "2021-08-01".parse().unwrap(),
94            ]
95        );
96
97        // https://doc.rust-lang.org/std/iter/trait.DoubleEndedIterator.html#examples
98        let mut iter = DateRangeIterator {
99            since: "2021-08-01".parse().unwrap(),
100            until: "2021-08-05".parse().unwrap(),
101        };
102        assert_eq!(iter.next(), Some("2021-08-01".parse().unwrap()));
103        assert_eq!(iter.next_back(), Some("2021-08-05".parse().unwrap()));
104        assert_eq!(iter.next_back(), Some("2021-08-04".parse().unwrap()));
105        assert_eq!(iter.next(), Some("2021-08-02".parse().unwrap()));
106        assert_eq!(iter.next(), Some("2021-08-03".parse().unwrap()));
107        assert_eq!(iter.next(), None);
108        assert_eq!(iter.next_back(), None);
109        assert_eq!(iter.since, "2021-08-04".parse().unwrap());
110        assert_eq!(iter.until, "2021-08-03".parse().unwrap());
111    }
112}