From 20030e38a921d2ba00ba7b67d0e466aafd591b4d Mon Sep 17 00:00:00 2001 From: metamuffin Date: Tue, 7 Jun 2022 11:42:46 +0200 Subject: a --- src/condition.rs | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 src/condition.rs (limited to 'src/condition.rs') diff --git a/src/condition.rs b/src/condition.rs new file mode 100644 index 0000000..7a873a8 --- /dev/null +++ b/src/condition.rs @@ -0,0 +1,156 @@ +use std::cmp::{max, min}; + +use chrono::{Datelike, NaiveDate, NaiveDateTime, NaiveTime}; +use serde::{Deserialize, Serialize}; +use Direction::*; +use Edge::*; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum Condition { + From(Box), + + Or(Vec), + And(Vec), + Invert(Box), + + Equal { + prop: Property, + value: i32, + modulus: Option, + }, + Range { + prop: Property, + min: i32, + max: i32, + modulus: Option, + }, +} + +#[derive(Debug, Clone, Copy, Serialize, Deserialize)] +pub enum Property { + Year, + Monthofyear, + Weekofmonth, + Dayofyear, + Dayofmonth, + Dayofweek, + Hour, + Minute, + Second, + Unix, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Range(T, T); +impl Range { + pub fn includes(&self, a: T) -> bool { + a > self.0 && a < self.1 + } +} + +#[derive(Debug, Clone, Copy)] +pub enum Edge { + Start, + End, +} +#[derive(Debug, Clone, Copy)] +pub enum Direction { + Forward, + Backward, +} + +impl Condition { + pub fn find(&self, edge: Edge, dir: Direction, from: NaiveDateTime) -> Option { + match self { + Condition::And(_) => todo!(), + 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 geq = match dir { + Forward => |a: i32, b: i32| a >= b, + Backward => |a: i32, b: i32| a < b, + }; + let off = match edge { + Start => 0, + End => 1, + }; + match prop { + Property::Year => { + if geq(from.year(), *value + off) { + None + } else { + Some(NaiveDateTime::new( + NaiveDate::from_ymd(*value + off, 1, 1), + NaiveTime::from_hms(0, 0, 0), + )) + } + } + Property::Monthofyear => todo!(), + Property::Weekofmonth => todo!(), + Property::Dayofyear => todo!(), + Property::Dayofmonth => todo!(), + Property::Dayofweek => todo!(), + Property::Hour => todo!(), + Property::Minute => todo!(), + Property::Second => todo!(), + Property::Unix => todo!(), + } + } + 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; + use std::str::FromStr; + + #[test] + fn a() { + 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); + } +} -- cgit v1.2.3-70-g09d2