chronos_parser_rs/
cron_interval_iterator.rs

1use crate::{CronInterval, Specification};
2use chrono::{DateTime, Duration, TimeZone};
3use std::rc::Rc;
4
5/// Iterator for The CronInterval.<br/>
6/// CronIntervalのためのイテレータ。
7#[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  /// The factory method.
17  /// ファクトリメソッド。
18  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  /// Returns the timezone of CronIntervalIterator.<br/>
55  /// CronIntervalIteratorのタイムゾーンを返す。
56  pub fn timezone(&self) -> &Tz {
57    &self.timezone
58  }
59
60  /// Returns the CronInterval.<br/>
61  /// CronIntervalを返す。
62  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}