aboutsummaryrefslogtreecommitdiff
path: root/src/condition.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/condition.rs')
-rw-r--r--src/condition.rs365
1 files changed, 0 insertions, 365 deletions
diff --git a/src/condition.rs b/src/condition.rs
deleted file mode 100644
index bc1b3ec..0000000
--- a/src/condition.rs
+++ /dev/null
@@ -1,365 +0,0 @@
-use std::cmp::{max, min};
-
-use chrono::{Datelike, Duration, NaiveDate, NaiveDateTime, NaiveTime, Timelike};
-use serde::{Deserialize, Serialize};
-use Direction::*;
-use Edge::*;
-
-#[derive(Debug, Clone, Serialize, Deserialize)]
-#[serde(rename_all = "snake_case")]
-pub enum Condition {
- From(Box<Condition>),
-
- Or(Vec<Condition>),
- And(Vec<Condition>),
- Invert(Box<Condition>),
-
- Equal {
- prop: Property,
- value: i64,
- modulus: Option<i64>,
- },
- Range {
- prop: Property,
- min: i64,
- max: i64,
- modulus: Option<i64>,
- },
-}
-
-#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
-#[serde(rename_all = "snake_case")]
-pub enum Property {
- Year,
- Monthofyear,
- Weekofmonth,
- Dayofyear,
- Dayofmonth,
- Dayofweek,
- Hour,
- Minute,
- Second,
- Unix,
-}
-
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct Range<T>(T, T);
-impl<T: PartialOrd + PartialEq> Range<T> {
- pub fn includes(&self, a: T) -> bool {
- a > self.0 && a < self.1
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub enum Edge {
- Start,
- End,
-}
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub enum Direction {
- Forward,
- Backward,
-}
-
-impl Condition {
- pub fn find(
- &self,
- edge: Edge,
- dir: Direction,
- mut from: NaiveDateTime,
- ) -> Option<NaiveDateTime> {
- match self {
- Condition::And(cs) => loop {
- // TODO improve efficiency for backward search
- let last_start = cs
- .iter()
- .map(|c| c.find(Start, dir, from))
- .reduce(|a, b| Some(max(a?, b?)))?;
- let first_end = cs
- .iter()
- .map(|c| c.find(End, dir, from))
- .reduce(|a, b| Some(min(a?, b?)))?;
- match last_start {
- Some(start) => match first_end {
- Some(end) => {
- if end > start {
- break Some(match edge {
- Start => start,
- End => end,
- });
- } else {
- from = start - Duration::seconds(10); // TODO proper fix
- }
- }
- None => break Some(start),
- },
- None => break None,
- }
- },
- Condition::Or(cs) => {
- cs.iter()
- .filter_map(|c| c.find(edge, dir, from))
- .reduce(match dir {
- Forward => min,
- Backward => max,
- })
- }
- Condition::From(_c) => todo!(),
- Condition::Invert(c) => c.find(edge.invert(), dir, from),
- Condition::Equal {
- prop,
- value,
- modulus: _,
- } => {
- let value = *value;
- let off: i64 = match edge {
- Start => 0,
- End => 1,
- };
- let dir_off = match dir {
- Forward => 0,
- Backward => -1,
- };
- match prop {
- Property::Year => {
- let geq = match dir {
- Forward => |a, b| a >= b,
- Backward => |a, b| a < b,
- };
-
- if geq(from.year(), (value + off) as i32) {
- None
- } else {
- Some(NaiveDateTime::new(
- NaiveDate::from_ymd((value + off) as i32, 1, 1),
- NaiveTime::from_hms(0, 0, 0),
- ))
- }
- }
- Property::Monthofyear => {
- let rollover = (value + off) / 12;
- let value = (value + off) % 12;
- // month still coming for this year
- if from.month0() < value as u32 {
- Some(NaiveDateTime::new(
- NaiveDate::from_ymd(
- from.year() + (rollover + dir_off) as i32,
- value as u32 + 1,
- 1,
- ),
- NaiveTime::from_hms(0, 0, 0),
- ))
- } else {
- Some(NaiveDateTime::new(
- NaiveDate::from_ymd(
- from.year() + (rollover + dir_off + 1) as i32,
- value as u32 + 1,
- 1,
- ),
- NaiveTime::from_hms(0, 0, 0),
- ))
- }
- }
- Property::Weekofmonth => todo!(),
- Property::Dayofyear => {
- todo!()
- }
- Property::Dayofmonth => {
- // let mut target = NaiveDateTime::new(
- // NaiveDate::from_ymd(from.year(), from.month(), value as u32),
- // NaiveTime::from_hms(0, 0, 0),
- // );
- // if edge == End {
- // target += Duration::days(1)
- // }
- // fn increment_month(d: NaiveDateTime) -> NaiveDateTime {
- // NaiveDateTime::new(
- // NaiveDate::from_ymd(
- // d.year() + (d.month() as i32 / 12),
- // (d.month() + 1) % 12,
- // d.day(),
- // ),
- // NaiveTime::from_hms(d.hour(), d.minute(), d.second()),
- // )
- // }
- // let dir_off = match dir {
- // Forward => |d| d,
- // Backward => increment_month,
- // };
- // if target > from {
- // Some(dir_off(target))
- // } else {
- // Some(increment_month(dir_off(target)))
- // }
- todo!()
- }
- Property::Dayofweek => todo!(),
- Property::Hour => {
- let mut target = NaiveDateTime::new(
- NaiveDate::from_ymd(from.year(), from.month(), from.day()),
- NaiveTime::from_hms(value as u32, 0, 0),
- );
- if edge == End {
- target += Duration::hours(1)
- }
- let dir_off = match dir {
- Forward => Duration::zero(),
- Backward => Duration::days(-1),
- };
- if target > from {
- Some(target + dir_off)
- } else {
- Some(target + dir_off + Duration::days(1))
- }
- }
- Property::Minute => {
- let mut target = NaiveDateTime::new(
- NaiveDate::from_ymd(from.year(), from.month(), from.day()),
- NaiveTime::from_hms(from.hour(), value as u32, 0),
- );
- if edge == End {
- target += Duration::minutes(1)
- }
- let dir_off = match dir {
- Forward => Duration::zero(),
- Backward => Duration::hours(-1),
- };
- if target > from {
- Some(target + dir_off)
- } else {
- Some(target + dir_off + Duration::hours(1))
- }
- }
- Property::Second => {
- let mut target = NaiveDateTime::new(
- NaiveDate::from_ymd(from.year(), from.month(), from.day()),
- NaiveTime::from_hms(from.hour(), from.minute(), value as u32),
- );
- if edge == End {
- target += Duration::seconds(1)
- }
- let dir_off = match dir {
- Forward => Duration::zero(),
- Backward => Duration::minutes(-1),
- };
- if target > from {
- Some(target + dir_off)
- } else {
- Some(target + dir_off + Duration::minutes(1))
- }
- }
- Property::Unix => {
- let geq = match dir {
- Forward => |a, b| a >= b,
- Backward => |a, b| a < b,
- };
- if geq(from.timestamp(), (value + off) as i64) {
- None
- } else {
- Some(NaiveDateTime::from_timestamp(value, 0))
- }
- }
- }
- }
- Condition::Range {
- prop: _,
- min: _,
- max: _,
- modulus: _,
- } => todo!(),
- }
- }
-}
-
-impl Edge {
- pub fn invert(self) -> Self {
- match self {
- Edge::Start => Edge::End,
- Edge::End => Edge::Start,
- }
- }
-}
-
-#[cfg(test)]
-mod test {
- use super::{Condition, Direction, Edge, Property};
- use chrono::{NaiveDateTime, Utc};
- use std::str::FromStr;
- use Direction::*;
- use Edge::*;
-
- #[test]
- fn blub() {
- let cond = Condition::And(vec![
- Condition::Equal {
- modulus: None,
- prop: Property::Monthofyear,
- value: 1,
- },
- Condition::Equal {
- modulus: None,
- prop: Property::Hour,
- value: 12,
- },
- ]);
- // let cond = Condition::Equal {
- // modulus: None,
- // prop: Property::Hour,
- // value: 12,
- // };
- let dt = Utc::now().naive_utc();
- println!("START FORWARD => {:?}", cond.find(Start, Forward, dt));
- println!("END FORWARD => {:?}", cond.find(End, Forward, dt));
- println!("START BACKWARD => {:?}", cond.find(Start, Backward, dt));
- println!("END BACKWARD => {:?}", cond.find(End, Backward, dt));
- }
-
- #[test]
- fn year_equal() {
- let cond = Condition::Equal {
- modulus: None,
- prop: Property::Year,
- value: 2023,
- };
-
- let dt = NaiveDateTime::from_str("2022-06-07T13:37:48").unwrap();
- assert_eq!(
- cond.find(Edge::Start, Direction::Forward, dt).unwrap(),
- NaiveDateTime::from_str("2023-01-01T00:00:00").unwrap(),
- );
- assert_eq!(
- cond.find(Edge::End, Direction::Forward, dt).unwrap(),
- NaiveDateTime::from_str("2024-01-01T00:00:00").unwrap(),
- );
- assert_eq!(cond.find(Edge::End, Direction::Backward, dt), None);
- assert_eq!(cond.find(Edge::Start, Direction::Backward, dt), None);
- }
-
- #[test]
- fn month_equal() {
- let cond = Condition::Equal {
- modulus: None,
- prop: Property::Monthofyear,
- value: 3,
- };
-
- let dt = NaiveDateTime::from_str("2022-06-07T13:37:48").unwrap();
-
- assert_eq!(
- cond.find(Edge::Start, Direction::Forward, dt),
- Some(NaiveDateTime::from_str("2023-04-01T00:00:00").unwrap())
- );
- assert_eq!(
- cond.find(Edge::End, Direction::Forward, dt),
- Some(NaiveDateTime::from_str("2023-05-01T00:00:00").unwrap())
- );
- assert_eq!(
- cond.find(Edge::Start, Direction::Backward, dt),
- Some(NaiveDateTime::from_str("2022-04-01T00:00:00").unwrap())
- );
- assert_eq!(
- cond.find(Edge::End, Direction::Backward, dt),
- Some(NaiveDateTime::from_str("2022-05-01T00:00:00").unwrap())
- );
- }
-}