chronos_parser_rs/
cron_interval_iterator.rs1use crate::{CronInterval, Specification};
2use chrono::{DateTime, Duration, TimeZone};
3use std::rc::Rc;
4
5#[derive(Debug, Clone)]
8pub struct CronIntervalIterator<Tz: TimeZone, S: Specification<DateTime<Tz>>> {
9 timezone: Tz,
10 curr: DateTime<Tz>,
11 next: DateTime<Tz>,
12 cron_interval: Rc<CronInterval<Tz, S>>,
13}
14
15impl<Tz: TimeZone, S: Specification<DateTime<Tz>>> CronIntervalIterator<Tz, S> {
16 pub fn new(timezone: Tz, curr: DateTime<Tz>, next: DateTime<Tz>, cron_interval: Rc<CronInterval<Tz, S>>) -> Self {
19 Self {
20 timezone,
21 curr,
22 next,
23 cron_interval,
24 }
25 }
26}
27
28impl<Tz: TimeZone, S: Specification<DateTime<Tz>>> Iterator for CronIntervalIterator<Tz, S> {
29 type Item = DateTime<Tz>;
30
31 fn next(&mut self) -> Option<Self::Item> {
32 self.curr = self.next.clone();
33 self.next = self.next.clone() + Duration::minutes(1);
34 match self.end_value() {
35 None => {
36 self.proceed_next();
37 let curr: DateTime<Tz> = self.curr.clone();
38 Some(curr)
39 }
40 Some(end) => {
41 if end >= self.curr {
42 self.proceed_next();
43 let curr: DateTime<Tz> = self.curr.clone();
44 Some(curr)
45 } else {
46 None
47 }
48 }
49 }
50 }
51}
52
53impl<Tz: TimeZone, S: Specification<DateTime<Tz>>> CronIntervalIterator<Tz, S> {
54 pub fn timezone(&self) -> &Tz {
57 &self.timezone
58 }
59
60 pub fn cron_interval(&self) -> Rc<CronInterval<Tz, S>> {
63 self.cron_interval.clone()
64 }
65
66 fn end_value(&self) -> Option<DateTime<Tz>> {
67 if self.cron_interval.underlying.has_upper_limit() {
68 let timestamp = self.cron_interval.underlying.as_upper_limit().as_value().unwrap();
69 let date_time = self.timezone.timestamp_millis_opt(*timestamp).unwrap();
70 Some(date_time)
71 } else {
72 None
73 }
74 }
75
76 fn proceed_next(&mut self) {
77 while !self.cron_interval.cron_specification.is_satisfied_by(&self.curr) {
78 self.curr = self.next.clone();
79 self.next = self.next.clone() + Duration::minutes(1);
80 }
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use chrono::{TimeZone, Utc};
87 use intervals_rs::LimitValue;
88
89 use crate::{CronInterval, CronParser, CronSpecification};
90
91 #[test]
92 fn test_iterator() {
93 let dt = Utc.with_ymd_and_hms(2021, 1, 1, 1, 1, 0).unwrap();
94
95 let expr = CronParser::parse("0-59/30 0-23/2 * * *").to_result().unwrap();
96 let interval = CronInterval::new(
97 LimitValue::Limit(dt),
98 LimitValue::Limitless,
99 CronSpecification::new(expr),
100 );
101 let itr = interval.iter(Utc);
102 itr.take(5).for_each(|e| println!("{:?}", e));
103 }
104}