#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate chrono;
use chrono::{DateTime, Local, Duration, TimeZone};
use chrono::naive::{MAX_DATE, MIN_DATE};
macro_rules! max_datetime {
() => (Local.from_utc_datetime(&MAX_DATE.and_hms(23, 11, 59)))
}
macro_rules! min_datetime {
() => (Local.from_utc_datetime(&MIN_DATE.and_hms(0, 0, 0)))
}
#[cfg(test)]
mod tests;
mod duration_format;
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ReDateTime {
pub at: DateTime<Local>,
#[serde(with = "duration_format")]
pub repeat: Duration,
pub until: DateTime<Local>,
}
#[derive(Debug)]
pub struct ReDateTimeIter<'a> {
from: &'a ReDateTime,
adder: Option<Duration>,
}
impl ReDateTime {
pub fn at(dt: DateTime<Local>) -> Self {
ReDateTime { at: dt, repeat: Duration::zero(), until: max_datetime!() }
}
pub fn repeat(dt: DateTime<Local>, dur: Duration) -> Self {
let lim = if dur < Duration::zero() { max_datetime!() } else { min_datetime!() };
ReDateTime { at: dt, repeat: dur, until: lim - dur }
}
pub fn repeat_until(dt: DateTime<Local>, dur: Duration, til: DateTime<Local>) -> Self {
ReDateTime { at: dt, repeat: dur, until: til - dur }
}
pub fn iter(&self) -> ReDateTimeIter {
let adr = if self.repeat.is_zero() { None } else { Some(Duration::zero()) };
ReDateTimeIter { from: &self, adder: adr }
}
}
impl<'a> Iterator for ReDateTimeIter<'a> {
type Item = DateTime<Local>;
fn next(&mut self) -> Option<Self::Item> {
if self.adder.is_none() {
return None;
}
let x = self.adder.unwrap();
self.adder = self.adder.unwrap().checked_add(&self.from.repeat);
let n = self.from.at + x;
if self.from.repeat < Duration::zero() {
if n >= self.from.until {
return Some(n);
}
} else if n <= self.from.until {
return Some(n);
}
None
}
}