kronos/
seq_seasons.rs

1#![deny(warnings)]
2
3use crate::utils;
4use crate::types::{Grain, DateTime, Range, TimeSequence, Season};
5
6
7#[derive(Clone)]
8pub struct Seasons(pub Season, pub bool); // north hemisphere
9
10impl Seasons {
11    fn _base(&self, t0: &DateTime, future: bool) -> Box<dyn Iterator<Item=Range>> {
12        let (s0, s1) = utils::find_season(t0.date(), self.0, future, self.1);
13        let s0 = s0.and_hms(0, 0, 0);
14        let s1 = s1.and_hms(0, 0, 0);
15        let sign = if future { 1 } else { -1 };
16        Box::new((0..).map(move |x| Range{
17            start: utils::shift_datetime(s0, Grain::Year, sign * x),
18            end: utils::shift_datetime(s1, Grain::Year, sign * x),
19            grain: Grain::Day
20        }))
21    }
22}
23
24impl TimeSequence for Seasons {
25    fn _future_raw(&self, t0: &DateTime) -> Box<dyn Iterator<Item=Range>> {
26        self._base(t0, true)
27    }
28
29    fn _past_raw(&self, t0: &DateTime) -> Box<dyn Iterator<Item=Range>> {
30        self._base(t0, false)
31    }
32}
33
34#[cfg(test)]
35mod test {
36    use super::*;
37    use crate::types::{Date, Grain};
38
39    fn dt(year: i32, month: u32, day: u32) -> DateTime {
40        Date::from_ymd(year, month, day).and_hms(0, 0, 0)
41    }
42
43    #[test]
44    fn summer() {
45        let summer = Seasons(Season::Summer, true);
46
47        let mut iter = summer.future(&dt(2015, 9, 22));
48        assert_eq!(iter.next().unwrap(),
49            Range{start: dt(2016, 6, 21), end: dt(2016, 9, 21), grain: Grain::Day});
50        assert_eq!(iter.next().unwrap(),
51            Range{start: dt(2017, 6, 21), end: dt(2017, 9, 21), grain: Grain::Day});
52
53        // past non-inclusive
54        let mut iter = summer.past(&dt(2015, 9, 22));
55        assert_eq!(iter.next().unwrap(),
56            Range{start: dt(2015, 6, 21), end: dt(2015, 9, 21), grain: Grain::Day});
57        assert_eq!(iter.next().unwrap(),
58            Range{start: dt(2014, 6, 21), end: dt(2014, 9, 21), grain: Grain::Day});
59    }
60
61    #[test]
62    fn winter() {
63        let winter = Seasons(Season::Winter, true);
64        // future
65        let mut iter = winter.future(&dt(2015, 1, 22));
66        assert_eq!(iter.next().unwrap(),
67            Range{start: dt(2014, 12, 21), end: dt(2015, 3, 21), grain: Grain::Day});
68        assert_eq!(iter.next().unwrap(),
69            Range{start: dt(2015, 12, 21), end: dt(2016, 3, 21), grain: Grain::Day});
70
71        // past non-inclusive
72        let mut iter = winter.past(&dt(2015, 1, 22));
73        assert_eq!(iter.next().unwrap(),
74            Range{start: dt(2013, 12, 21), end: dt(2014, 3, 21), grain: Grain::Day});
75        assert_eq!(iter.next().unwrap(),
76            Range{start: dt(2012, 12, 21), end: dt(2013, 3, 21), grain: Grain::Day});
77
78        // past inclusive
79        let mut iter = winter._past_raw(&dt(2015, 1, 22));
80        assert_eq!(iter.next().unwrap(),
81            Range{start: dt(2014, 12, 21), end: dt(2015, 3, 21), grain: Grain::Day});
82        assert_eq!(iter.next().unwrap(),
83            Range{start: dt(2013, 12, 21), end: dt(2014, 3, 21), grain: Grain::Day});
84    }
85}