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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
use super::{Duration, Epoch};
#[derive(Clone, Debug)]
pub struct TimeSeries {
start: Epoch,
end: Epoch,
step: Duration,
cur: Epoch,
incl: bool,
}
impl TimeSeries {
#[inline]
pub fn exclusive(start: Epoch, end: Epoch, step: Duration) -> TimeSeries {
Self {
start,
end,
step,
cur: start - step,
incl: false,
}
}
#[inline]
pub fn inclusive(start: Epoch, end: Epoch, step: Duration) -> TimeSeries {
Self {
start,
end,
step,
cur: start - step,
incl: true,
}
}
}
impl Iterator for TimeSeries {
type Item = Epoch;
#[inline]
fn next(&mut self) -> Option<Epoch> {
let next_item = self.cur + self.step;
if (!self.incl && next_item >= self.end) || (self.incl && next_item > self.end) {
None
} else {
self.cur = next_item;
Some(next_item)
}
}
}
impl DoubleEndedIterator for TimeSeries {
#[inline]
fn next_back(&mut self) -> Option<Epoch> {
let next_item = self.cur - self.step;
if next_item < self.start {
None
} else {
Some(next_item)
}
}
}
impl ExactSizeIterator for TimeSeries where TimeSeries: Iterator {}
#[cfg(test)]
mod tests {
use crate::{Epoch, TimeSeries, Unit};
#[test]
fn test_timeseries() {
let start = Epoch::from_gregorian_utc_at_midnight(2017, 1, 14);
let end = Epoch::from_gregorian_utc_at_noon(2017, 1, 14);
let step = Unit::Hour * 2;
let mut count = 0;
let time_series = TimeSeries::exclusive(start, end, step);
for epoch in time_series {
if count == 0 {
assert_eq!(
epoch, start,
"Starting epoch of exclusive time series is wrong"
);
} else if count == 5 {
assert_ne!(epoch, end, "Ending epoch of exclusive time series is wrong");
}
#[cfg(feature = "std")]
println!("{}", epoch);
count += 1;
}
assert_eq!(count, 6, "Should have five items in this iterator");
count = 0;
let time_series = TimeSeries::inclusive(start, end, step);
for epoch in time_series {
if count == 0 {
assert_eq!(
epoch, start,
"Starting epoch of inclusive time series is wrong"
);
} else if count == 6 {
assert_eq!(epoch, end, "Ending epoch of inclusive time series is wrong");
}
#[cfg(feature = "std")]
println!("{}", epoch);
count += 1;
}
assert_eq!(count, 7, "Should have six items in this iterator");
}
}