1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
use core::{
    iter::{DoubleEndedIterator, IntoIterator, Iterator},
    mem,
};

use chrono::{Duration, NaiveDate};

use crate::DateRange;

#[derive(Debug, Clone, PartialEq)]
pub struct DateRangeIterator {
    since: NaiveDate,
    until: NaiveDate,
}

// https://stackoverflow.com/questions/41679239/loop-over-date-range
impl Iterator for DateRangeIterator {
    type Item = NaiveDate;
    fn next(&mut self) -> Option<Self::Item> {
        if self.since <= self.until {
            let next_front = self.since + Duration::days(1);
            Some(mem::replace(&mut self.since, next_front))
        } else {
            None
        }
    }
}
impl DoubleEndedIterator for DateRangeIterator {
    fn next_back(&mut self) -> Option<Self::Item> {
        if self.since <= self.until {
            let next_back = self.until - Duration::days(1);
            Some(mem::replace(&mut self.until, next_back))
        } else {
            None
        }
    }
}

impl IntoIterator for DateRange {
    type Item = NaiveDate;

    type IntoIter = DateRangeIterator;

    fn into_iter(self) -> Self::IntoIter {
        DateRangeIterator {
            since: self.since(),
            until: self.until(),
        }
    }
}
impl IntoIterator for &DateRange {
    type Item = NaiveDate;

    type IntoIter = DateRangeIterator;

    fn into_iter(self) -> Self::IntoIter {
        DateRangeIterator {
            since: self.since(),
            until: self.until(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn simple() {
        assert_eq!(
            DateRange::new("2021-08-01".parse().unwrap(), "2021-08-05".parse().unwrap())
                .unwrap()
                .into_iter()
                .collect::<Vec<_>>(),
            vec![
                "2021-08-01".parse().unwrap(),
                "2021-08-02".parse().unwrap(),
                "2021-08-03".parse().unwrap(),
                "2021-08-04".parse().unwrap(),
                "2021-08-05".parse().unwrap(),
            ]
        );

        let date_range =
            &DateRange::new("2021-08-01".parse().unwrap(), "2021-08-05".parse().unwrap()).unwrap();
        assert_eq!(
            date_range.into_iter().rev().collect::<Vec<_>>(),
            vec![
                "2021-08-05".parse().unwrap(),
                "2021-08-04".parse().unwrap(),
                "2021-08-03".parse().unwrap(),
                "2021-08-02".parse().unwrap(),
                "2021-08-01".parse().unwrap(),
            ]
        );

        // https://doc.rust-lang.org/std/iter/trait.DoubleEndedIterator.html#examples
        let mut iter = DateRangeIterator {
            since: "2021-08-01".parse().unwrap(),
            until: "2021-08-05".parse().unwrap(),
        };
        assert_eq!(iter.next(), Some("2021-08-01".parse().unwrap()));
        assert_eq!(iter.next_back(), Some("2021-08-05".parse().unwrap()));
        assert_eq!(iter.next_back(), Some("2021-08-04".parse().unwrap()));
        assert_eq!(iter.next(), Some("2021-08-02".parse().unwrap()));
        assert_eq!(iter.next(), Some("2021-08-03".parse().unwrap()));
        assert_eq!(iter.next(), None);
        assert_eq!(iter.next_back(), None);
        assert_eq!(iter.since, "2021-08-04".parse().unwrap());
        assert_eq!(iter.until, "2021-08-03".parse().unwrap());
    }
}