1#[macro_use]
2extern crate serde_derive;
3extern crate serde;
4extern crate chrono;
5
6use chrono::{DateTime, Utc, TimeZone};
7use chrono::naive::{MAX_DATE, MIN_DATE};
8
9macro_rules! max_datetime {
10 () => (Utc.from_utc_datetime(&MAX_DATE.and_hms(23, 59, 59)))
11}
12
13macro_rules! min_datetime {
14 () => (Utc.from_utc_datetime(&MIN_DATE.and_hms(0, 0, 0)))
15}
16
17#[cfg(test)]
18mod tests;
19pub mod repeat_every;
20
21use repeat_every::RepeatEvery;
22
23#[derive(Serialize, Deserialize, Clone, Debug)]
26pub struct ReDateTime {
27 pub at: DateTime<Utc>,
28 pub repeat: RepeatEvery,
29 pub until: DateTime<Utc>,
30}
31
32#[derive(Debug)]
33pub struct ReDateTimeIter<'a> {
34 from: &'a ReDateTime,
35 adder: Option<RepeatEvery>,
36}
37
38impl ReDateTime {
39 pub fn at(dt: DateTime<Utc>) -> Self {
41 ReDateTime { at: dt, repeat: RepeatEvery::zero(), until: max_datetime!() }
42 }
43
44 pub fn repeat(dt: DateTime<Utc>, dur: RepeatEvery) -> Self {
46 let lim = if dur.is_zero() { min_datetime!() } else { max_datetime!()
47 };
48 ReDateTime { at: dt, repeat: dur, until: lim }
49 }
50
51 pub fn repeat_until(dt: DateTime<Utc>, dur: RepeatEvery, til: DateTime<Utc>) -> Self {
53 ReDateTime { at: dt, repeat: dur, until: til }
54 }
55
56 pub fn done_before(&self, dt: &DateTime<Utc>) -> bool {
58 if self.repeat.is_zero() {
59 return self.at < *dt;
60 }
61
62 self.until != max_datetime!()
63 && (self.until < *dt || self.iter().last().unwrap() < *dt)
64 }
65
66 pub fn between(&self, df: &DateTime<Utc>, dt: &DateTime<Utc>) -> bool {
68 self.first_after(df).map_or(false, |d| d <= *dt)
69 }
70
71 pub fn first_after(&self, df: &DateTime<Utc>) -> Option<DateTime<Utc>> {
73 if self.repeat.is_zero() {
74 if self.at < *df {
75 None
76 } else {
77 Some(self.at)
78 }
79 } else {
80 if self.until < *df {
81 None
82 } else {
83 self.iter().skip_while(|x| *x < *df).next()
84 }
85 }
86 }
87
88 pub fn iter(&self) -> ReDateTimeIter {
90 let a = if self.repeat.is_zero() {
91 None } else {
92 Some(RepeatEvery::zero())
93 };
94 ReDateTimeIter { from: &self, adder: a }
95 }
96}
97
98impl<'a> Iterator for ReDateTimeIter<'a> {
99 type Item = DateTime<Utc>;
100
101 fn next(&mut self) -> Option<Self::Item> {
102 if self.adder.is_none() {
103 return None;
104 }
105
106 let x = self.adder.clone().unwrap();
107 self.adder = x.checked_add(&self.from.repeat);
108 if let Some(n) = x.add_to(&self.from.at) {
109 if n <= self.from.until {
110 return Some(n);
111 }
112 }
113 None
114 }
115}