From 0f294cf2e105a30aa1358ac70f3acd00a01624b7 Mon Sep 17 00:00:00 2001 From: Lennart <18233294+lennart-k@users.noreply.github.com> Date: Sun, 18 May 2025 14:35:01 +0200 Subject: [PATCH] Datetime ordering and chrono Weekdays --- Cargo.toml | 1 + crates/ical/src/rrule/mod.rs | 46 ++++++++++++++++++++++++------------ crates/ical/src/timestamp.rs | 15 +----------- 3 files changed, 33 insertions(+), 29 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4d52f9b..46ce990 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,6 +72,7 @@ derive_more = { version = "2.0", features = [ "into", "deref", "constructor", + "display", ] } askama = { version = "0.14", features = ["serde_json"] } askama_web = { version = "0.14.0", features = ["actix-web-4"] } diff --git a/crates/ical/src/rrule/mod.rs b/crates/ical/src/rrule/mod.rs index f025439..a6520cb 100644 --- a/crates/ical/src/rrule/mod.rs +++ b/crates/ical/src/rrule/mod.rs @@ -1,4 +1,5 @@ use super::{CalDateTime, CalDateTimeError}; +use chrono::Weekday; use std::{num::ParseIntError, str::FromStr}; use strum_macros::EnumString; @@ -33,7 +34,7 @@ pub enum RecurrenceFrequency { #[derive(Debug, Clone, EnumString, PartialEq)] #[strum(serialize_all = "UPPERCASE")] -pub enum Weekday { +pub enum IcalWeekday { Mo, Tu, We, @@ -43,6 +44,20 @@ pub enum Weekday { Su, } +impl From for Weekday { + fn from(value: IcalWeekday) -> Self { + match value { + IcalWeekday::Mo => Self::Mon, + IcalWeekday::Tu => Self::Tue, + IcalWeekday::We => Self::Wed, + IcalWeekday::Th => Self::Thu, + IcalWeekday::Fr => Self::Fri, + IcalWeekday::Sa => Self::Sat, + IcalWeekday::Su => Self::Sun, + } + } +} + #[derive(Debug, Clone, PartialEq)] pub enum RecurrenceLimit { Count(usize), @@ -126,7 +141,8 @@ impl RecurrenceRule { .map(|val| { assert!(val.len() >= 2); let weekday = - Weekday::from_str(val.get((val.len() - 2)..).unwrap())?; + IcalWeekday::from_str(val.get((val.len() - 2)..).unwrap())? + .into(); let prefix = if val.len() > 2 { Some(val.get(..(val.len() - 2)).unwrap().parse()?) } else { @@ -165,7 +181,7 @@ impl RecurrenceRule { .collect::, _>>()?, ); } - ("WKST", val) => week_start = Some(Weekday::from_str(val)?), + ("WKST", val) => week_start = Some(IcalWeekday::from_str(val)?.into()), ("BYSETPOS", val) => { bysetpos = Some( val.split(',') @@ -196,12 +212,12 @@ impl RecurrenceRule { #[cfg(test)] mod tests { + use super::{ParserError, RecurrenceRule}; use crate::{ CalDateTime, - rrule::{RecurrenceFrequency, RecurrenceLimit, Weekday}, + rrule::{RecurrenceFrequency, RecurrenceLimit}, }; - - use super::{ParserError, RecurrenceRule}; + use chrono::Weekday; #[test] fn parse_recurrence_rule() -> Result<(), ParserError> { @@ -223,9 +239,9 @@ mod tests { limit: Some(RecurrenceLimit::Count(4)), interval: 2, byday: Some(vec![ - (None, Weekday::Tu), - (None, Weekday::Th), - (None, Weekday::Su), + (None, Weekday::Tue), + (None, Weekday::Thu), + (None, Weekday::Sun), ]), ..Default::default() } @@ -236,11 +252,11 @@ mod tests { RecurrenceRule { frequency: RecurrenceFrequency::Monthly, byday: Some(vec![ - (None, Weekday::Mo), - (None, Weekday::Tu), - (None, Weekday::We), - (None, Weekday::Th), - (None, Weekday::Fr), + (None, Weekday::Mon), + (None, Weekday::Tue), + (None, Weekday::Wed), + (None, Weekday::Thu), + (None, Weekday::Fri), ]), bysetpos: Some(vec![-1]), ..Default::default() @@ -255,7 +271,7 @@ mod tests { limit: Some(RecurrenceLimit::Until( CalDateTime::parse("20370329T010000Z", None).unwrap() )), - byday: Some(vec![(Some(-1), Weekday::Su)]), + byday: Some(vec![(Some(-1), Weekday::Sun)]), bymonth: Some(vec![3]), ..Default::default() } diff --git a/crates/ical/src/timestamp.rs b/crates/ical/src/timestamp.rs index 8757521..9b9674c 100644 --- a/crates/ical/src/timestamp.rs +++ b/crates/ical/src/timestamp.rs @@ -62,7 +62,7 @@ impl ValueSerialize for UtcDateTime { } } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)] pub enum CalDateTime { // Form 1, example: 19980118T230000 -> Local // Form 2, example: 19980119T070000Z -> UTC @@ -256,84 +256,72 @@ impl Datelike for CalDateTime { CalDateTime::Date(date) => date.month0(), } } - fn day(&self) -> u32 { match &self { CalDateTime::DateTime(datetime) => datetime.day(), CalDateTime::Date(date) => date.day(), } } - fn day0(&self) -> u32 { match &self { CalDateTime::DateTime(datetime) => datetime.day0(), CalDateTime::Date(date) => date.day0(), } } - fn ordinal(&self) -> u32 { match &self { CalDateTime::DateTime(datetime) => datetime.ordinal(), CalDateTime::Date(date) => date.ordinal(), } } - fn ordinal0(&self) -> u32 { match &self { CalDateTime::DateTime(datetime) => datetime.ordinal0(), CalDateTime::Date(date) => date.ordinal0(), } } - fn weekday(&self) -> chrono::Weekday { match &self { CalDateTime::DateTime(datetime) => datetime.weekday(), CalDateTime::Date(date) => date.weekday(), } } - fn iso_week(&self) -> chrono::IsoWeek { match &self { CalDateTime::DateTime(datetime) => datetime.iso_week(), CalDateTime::Date(date) => date.iso_week(), } } - fn with_year(&self, year: i32) -> Option { match &self { CalDateTime::DateTime(datetime) => Some(Self::DateTime(datetime.with_year(year)?)), CalDateTime::Date(date) => Some(Self::Date(date.with_year(year)?)), } } - fn with_month(&self, month: u32) -> Option { match &self { CalDateTime::DateTime(datetime) => Some(Self::DateTime(datetime.with_month(month)?)), CalDateTime::Date(date) => Some(Self::Date(date.with_month(month)?)), } } - fn with_month0(&self, month0: u32) -> Option { match &self { CalDateTime::DateTime(datetime) => Some(Self::DateTime(datetime.with_month0(month0)?)), CalDateTime::Date(date) => Some(Self::Date(date.with_month0(month0)?)), } } - fn with_day(&self, day: u32) -> Option { match &self { CalDateTime::DateTime(datetime) => Some(Self::DateTime(datetime.with_day(day)?)), CalDateTime::Date(date) => Some(Self::Date(date.with_day(day)?)), } } - fn with_day0(&self, day0: u32) -> Option { match &self { CalDateTime::DateTime(datetime) => Some(Self::DateTime(datetime.with_day0(day0)?)), CalDateTime::Date(date) => Some(Self::Date(date.with_day0(day0)?)), } } - fn with_ordinal(&self, ordinal: u32) -> Option { match &self { CalDateTime::DateTime(datetime) => { @@ -342,7 +330,6 @@ impl Datelike for CalDateTime { CalDateTime::Date(date) => Some(Self::Date(date.with_ordinal(ordinal)?)), } } - fn with_ordinal0(&self, ordinal0: u32) -> Option { match &self { CalDateTime::DateTime(datetime) => {