1#![deny(warnings)]
2
3use crate::types::{DateTime, Range, TimeSequence};
4
5#[derive(Clone)]
22pub struct Union<SeqA, SeqB>(pub SeqA, pub SeqB)
23 where SeqA: TimeSequence,
24 SeqB: TimeSequence;
25
26impl<SeqA, SeqB> Union<SeqA, SeqB>
27 where SeqA: TimeSequence,
28 SeqB: TimeSequence
29{
30 fn _base(&self, t0: &DateTime, future: bool) -> Box<dyn Iterator<Item=Range> + '_> {
31 let (mut astream, mut bstream) = if future {
32 (self.0._future_raw(t0), self.1._future_raw(t0))
33 } else {
34 (self.0._past_raw(t0), self.1._past_raw(t0))
35 };
36 let mut anext = astream.next().unwrap();
37 let mut bnext = bstream.next().unwrap();
38 Box::new((0..).map(move |_| {
39 if (anext.start <= bnext.start && future) ||
40 (anext.start > bnext.start && !future) {
41 while (bnext.end <= anext.end && future) ||
43 (bnext.start >= anext.start && !future) {
44 bnext = bstream.next().unwrap();
45 }
46 let unionret = anext.clone();
47 anext = astream.next().unwrap();
48 unionret
49 } else {
50 while (anext.end <= bnext.end && future) ||
52 (anext.start >= bnext.start && !future) {
53 anext = astream.next().unwrap();
54 }
55 let unionret = bnext.clone();
56 bnext = bstream.next().unwrap();
57 unionret
58 }
59 }))
60 }
61}
62
63impl<SeqA, SeqB> TimeSequence for Union<SeqA, SeqB>
64 where SeqA: TimeSequence,
65 SeqB: TimeSequence
66{
67 fn _future_raw(&self, t0: &DateTime) -> Box<dyn Iterator<Item=Range> + '_> {
68 self._base(t0, true)
69 }
70
71 fn _past_raw(&self, t0: &DateTime) -> Box<dyn Iterator<Item=Range> + '_> {
72 self._base(t0, false)
73 }
74}
75
76
77#[cfg(test)]
78mod test {
79 use super::*;
80 use crate::types::Grain;
81
82 fn dt(year: i32, month: u32, day: u32) -> DateTime {
83 use crate::types::Date;
84 Date::from_ymd(year, month, day).and_hms(0, 0, 0)
85 }
86
87 #[test]
88 fn test_union() {
89 use crate::seq_named::Weekday;
90
91 let mut monwed = Union(Weekday(1), Weekday(3)).future(&dt(2015, 2, 27));
92 assert_eq!(monwed.next().unwrap(),
93 Range{start: dt(2015, 3, 2), end: dt(2015, 3, 3), grain: Grain::Day});
94 assert_eq!(monwed.next().unwrap(),
95 Range{start: dt(2015, 3, 4), end: dt(2015, 3, 5), grain: Grain::Day});
96 assert_eq!(monwed.next().unwrap(),
97 Range{start: dt(2015, 3, 9), end: dt(2015, 3, 10), grain: Grain::Day});
98
99 let monwed = Union(Weekday(1), Weekday(3));
100 let monwedfri = Union(monwed, Weekday(5));
101 let mut monwedfri = monwedfri.future(&dt(2015, 2, 27));
102 assert_eq!(monwedfri.next().unwrap(),
103 Range{start: dt(2015, 2, 27), end: dt(2015, 2, 28), grain: Grain::Day});
104 assert_eq!(monwedfri.next().unwrap(),
105 Range{start: dt(2015, 3, 2), end: dt(2015, 3, 3), grain: Grain::Day});
106 assert_eq!(monwedfri.next().unwrap(),
107 Range{start: dt(2015, 3, 4), end: dt(2015, 3, 5), grain: Grain::Day});
108 }
109
110 #[test]
111 fn test_union_past() {
112 use crate::seq_named::Weekday;
113
114 let mut monwed = Union(Weekday(1), Weekday(3)).past(&dt(2015, 2, 27));
115 assert_eq!(monwed.next().unwrap(),
116 Range{start: dt(2015, 2, 25), end: dt(2015, 2, 26), grain: Grain::Day});
117 assert_eq!(monwed.next().unwrap(),
118 Range{start: dt(2015, 2, 23), end: dt(2015, 2, 24), grain: Grain::Day});
119
120 let monwed = Union(Weekday(1), Weekday(3));
121 let monwedfri = Union(monwed, Weekday(5));
122 let mut monwedfri = monwedfri.past(&dt(2015, 2, 27));
123 assert_eq!(monwedfri.next().unwrap(),
124 Range{start: dt(2015, 2, 25), end: dt(2015, 2, 26), grain: Grain::Day});
125 assert_eq!(monwedfri.next().unwrap(),
126 Range{start: dt(2015, 2, 23), end: dt(2015, 2, 24), grain: Grain::Day});
127 assert_eq!(monwedfri.next().unwrap(),
128 Range{start: dt(2015, 2, 20), end: dt(2015, 2, 21), grain: Grain::Day});
129
130 let monwed = Union(Weekday(1), Weekday(3));
132 let monwedfri = Union(monwed, Weekday(5));
133 let mut monwedfri = monwedfri._past_raw(&dt(2015, 2, 27));
134 assert_eq!(monwedfri.next().unwrap(),
135 Range{start: dt(2015, 2, 27), end: dt(2015, 2, 28), grain: Grain::Day});
136 }
137
138 #[test]
139 fn test_diff_resolution() {
140 use crate::seq_named::{Month, Weekday};
141
142 let mut mon_or_march = Union(Weekday(1), Month(3)).future(&dt(2015, 2, 27));
143 assert_eq!(mon_or_march.next().unwrap(),
144 Range{start: dt(2015, 3, 1), end: dt(2015, 4, 1), grain: Grain::Month});
145 assert_eq!(mon_or_march.next().unwrap(),
146 Range{start: dt(2015, 4, 6), end: dt(2015, 4, 7), grain: Grain::Day});
147 assert_eq!(mon_or_march.next().unwrap(),
148 Range{start: dt(2015, 4, 13), end: dt(2015, 4, 14), grain: Grain::Day});
149 let mut mon_or_march = mon_or_march.skip(46);
150 assert_eq!(mon_or_march.next().unwrap(),
151 Range{start: dt(2016, 3, 1), end: dt(2016, 4, 1), grain: Grain::Month});
152 }
153}