Datetime ordering and chrono Weekdays

This commit is contained in:
Lennart
2025-05-18 14:35:01 +02:00
parent fb8889b5f6
commit 0f294cf2e1
3 changed files with 33 additions and 29 deletions

View File

@@ -72,6 +72,7 @@ derive_more = { version = "2.0", features = [
"into", "into",
"deref", "deref",
"constructor", "constructor",
"display",
] } ] }
askama = { version = "0.14", features = ["serde_json"] } askama = { version = "0.14", features = ["serde_json"] }
askama_web = { version = "0.14.0", features = ["actix-web-4"] } askama_web = { version = "0.14.0", features = ["actix-web-4"] }

View File

@@ -1,4 +1,5 @@
use super::{CalDateTime, CalDateTimeError}; use super::{CalDateTime, CalDateTimeError};
use chrono::Weekday;
use std::{num::ParseIntError, str::FromStr}; use std::{num::ParseIntError, str::FromStr};
use strum_macros::EnumString; use strum_macros::EnumString;
@@ -33,7 +34,7 @@ pub enum RecurrenceFrequency {
#[derive(Debug, Clone, EnumString, PartialEq)] #[derive(Debug, Clone, EnumString, PartialEq)]
#[strum(serialize_all = "UPPERCASE")] #[strum(serialize_all = "UPPERCASE")]
pub enum Weekday { pub enum IcalWeekday {
Mo, Mo,
Tu, Tu,
We, We,
@@ -43,6 +44,20 @@ pub enum Weekday {
Su, Su,
} }
impl From<IcalWeekday> 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)] #[derive(Debug, Clone, PartialEq)]
pub enum RecurrenceLimit { pub enum RecurrenceLimit {
Count(usize), Count(usize),
@@ -126,7 +141,8 @@ impl RecurrenceRule {
.map(|val| { .map(|val| {
assert!(val.len() >= 2); assert!(val.len() >= 2);
let weekday = 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 { let prefix = if val.len() > 2 {
Some(val.get(..(val.len() - 2)).unwrap().parse()?) Some(val.get(..(val.len() - 2)).unwrap().parse()?)
} else { } else {
@@ -165,7 +181,7 @@ impl RecurrenceRule {
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
); );
} }
("WKST", val) => week_start = Some(Weekday::from_str(val)?), ("WKST", val) => week_start = Some(IcalWeekday::from_str(val)?.into()),
("BYSETPOS", val) => { ("BYSETPOS", val) => {
bysetpos = Some( bysetpos = Some(
val.split(',') val.split(',')
@@ -196,12 +212,12 @@ impl RecurrenceRule {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{ParserError, RecurrenceRule};
use crate::{ use crate::{
CalDateTime, CalDateTime,
rrule::{RecurrenceFrequency, RecurrenceLimit, Weekday}, rrule::{RecurrenceFrequency, RecurrenceLimit},
}; };
use chrono::Weekday;
use super::{ParserError, RecurrenceRule};
#[test] #[test]
fn parse_recurrence_rule() -> Result<(), ParserError> { fn parse_recurrence_rule() -> Result<(), ParserError> {
@@ -223,9 +239,9 @@ mod tests {
limit: Some(RecurrenceLimit::Count(4)), limit: Some(RecurrenceLimit::Count(4)),
interval: 2, interval: 2,
byday: Some(vec![ byday: Some(vec![
(None, Weekday::Tu), (None, Weekday::Tue),
(None, Weekday::Th), (None, Weekday::Thu),
(None, Weekday::Su), (None, Weekday::Sun),
]), ]),
..Default::default() ..Default::default()
} }
@@ -236,11 +252,11 @@ mod tests {
RecurrenceRule { RecurrenceRule {
frequency: RecurrenceFrequency::Monthly, frequency: RecurrenceFrequency::Monthly,
byday: Some(vec![ byday: Some(vec![
(None, Weekday::Mo), (None, Weekday::Mon),
(None, Weekday::Tu), (None, Weekday::Tue),
(None, Weekday::We), (None, Weekday::Wed),
(None, Weekday::Th), (None, Weekday::Thu),
(None, Weekday::Fr), (None, Weekday::Fri),
]), ]),
bysetpos: Some(vec![-1]), bysetpos: Some(vec![-1]),
..Default::default() ..Default::default()
@@ -255,7 +271,7 @@ mod tests {
limit: Some(RecurrenceLimit::Until( limit: Some(RecurrenceLimit::Until(
CalDateTime::parse("20370329T010000Z", None).unwrap() CalDateTime::parse("20370329T010000Z", None).unwrap()
)), )),
byday: Some(vec![(Some(-1), Weekday::Su)]), byday: Some(vec![(Some(-1), Weekday::Sun)]),
bymonth: Some(vec![3]), bymonth: Some(vec![3]),
..Default::default() ..Default::default()
} }

View File

@@ -62,7 +62,7 @@ impl ValueSerialize for UtcDateTime {
} }
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub enum CalDateTime { pub enum CalDateTime {
// Form 1, example: 19980118T230000 -> Local // Form 1, example: 19980118T230000 -> Local
// Form 2, example: 19980119T070000Z -> UTC // Form 2, example: 19980119T070000Z -> UTC
@@ -256,84 +256,72 @@ impl Datelike for CalDateTime {
CalDateTime::Date(date) => date.month0(), CalDateTime::Date(date) => date.month0(),
} }
} }
fn day(&self) -> u32 { fn day(&self) -> u32 {
match &self { match &self {
CalDateTime::DateTime(datetime) => datetime.day(), CalDateTime::DateTime(datetime) => datetime.day(),
CalDateTime::Date(date) => date.day(), CalDateTime::Date(date) => date.day(),
} }
} }
fn day0(&self) -> u32 { fn day0(&self) -> u32 {
match &self { match &self {
CalDateTime::DateTime(datetime) => datetime.day0(), CalDateTime::DateTime(datetime) => datetime.day0(),
CalDateTime::Date(date) => date.day0(), CalDateTime::Date(date) => date.day0(),
} }
} }
fn ordinal(&self) -> u32 { fn ordinal(&self) -> u32 {
match &self { match &self {
CalDateTime::DateTime(datetime) => datetime.ordinal(), CalDateTime::DateTime(datetime) => datetime.ordinal(),
CalDateTime::Date(date) => date.ordinal(), CalDateTime::Date(date) => date.ordinal(),
} }
} }
fn ordinal0(&self) -> u32 { fn ordinal0(&self) -> u32 {
match &self { match &self {
CalDateTime::DateTime(datetime) => datetime.ordinal0(), CalDateTime::DateTime(datetime) => datetime.ordinal0(),
CalDateTime::Date(date) => date.ordinal0(), CalDateTime::Date(date) => date.ordinal0(),
} }
} }
fn weekday(&self) -> chrono::Weekday { fn weekday(&self) -> chrono::Weekday {
match &self { match &self {
CalDateTime::DateTime(datetime) => datetime.weekday(), CalDateTime::DateTime(datetime) => datetime.weekday(),
CalDateTime::Date(date) => date.weekday(), CalDateTime::Date(date) => date.weekday(),
} }
} }
fn iso_week(&self) -> chrono::IsoWeek { fn iso_week(&self) -> chrono::IsoWeek {
match &self { match &self {
CalDateTime::DateTime(datetime) => datetime.iso_week(), CalDateTime::DateTime(datetime) => datetime.iso_week(),
CalDateTime::Date(date) => date.iso_week(), CalDateTime::Date(date) => date.iso_week(),
} }
} }
fn with_year(&self, year: i32) -> Option<Self> { fn with_year(&self, year: i32) -> Option<Self> {
match &self { match &self {
CalDateTime::DateTime(datetime) => Some(Self::DateTime(datetime.with_year(year)?)), CalDateTime::DateTime(datetime) => Some(Self::DateTime(datetime.with_year(year)?)),
CalDateTime::Date(date) => Some(Self::Date(date.with_year(year)?)), CalDateTime::Date(date) => Some(Self::Date(date.with_year(year)?)),
} }
} }
fn with_month(&self, month: u32) -> Option<Self> { fn with_month(&self, month: u32) -> Option<Self> {
match &self { match &self {
CalDateTime::DateTime(datetime) => Some(Self::DateTime(datetime.with_month(month)?)), CalDateTime::DateTime(datetime) => Some(Self::DateTime(datetime.with_month(month)?)),
CalDateTime::Date(date) => Some(Self::Date(date.with_month(month)?)), CalDateTime::Date(date) => Some(Self::Date(date.with_month(month)?)),
} }
} }
fn with_month0(&self, month0: u32) -> Option<Self> { fn with_month0(&self, month0: u32) -> Option<Self> {
match &self { match &self {
CalDateTime::DateTime(datetime) => Some(Self::DateTime(datetime.with_month0(month0)?)), CalDateTime::DateTime(datetime) => Some(Self::DateTime(datetime.with_month0(month0)?)),
CalDateTime::Date(date) => Some(Self::Date(date.with_month0(month0)?)), CalDateTime::Date(date) => Some(Self::Date(date.with_month0(month0)?)),
} }
} }
fn with_day(&self, day: u32) -> Option<Self> { fn with_day(&self, day: u32) -> Option<Self> {
match &self { match &self {
CalDateTime::DateTime(datetime) => Some(Self::DateTime(datetime.with_day(day)?)), CalDateTime::DateTime(datetime) => Some(Self::DateTime(datetime.with_day(day)?)),
CalDateTime::Date(date) => Some(Self::Date(date.with_day(day)?)), CalDateTime::Date(date) => Some(Self::Date(date.with_day(day)?)),
} }
} }
fn with_day0(&self, day0: u32) -> Option<Self> { fn with_day0(&self, day0: u32) -> Option<Self> {
match &self { match &self {
CalDateTime::DateTime(datetime) => Some(Self::DateTime(datetime.with_day0(day0)?)), CalDateTime::DateTime(datetime) => Some(Self::DateTime(datetime.with_day0(day0)?)),
CalDateTime::Date(date) => Some(Self::Date(date.with_day0(day0)?)), CalDateTime::Date(date) => Some(Self::Date(date.with_day0(day0)?)),
} }
} }
fn with_ordinal(&self, ordinal: u32) -> Option<Self> { fn with_ordinal(&self, ordinal: u32) -> Option<Self> {
match &self { match &self {
CalDateTime::DateTime(datetime) => { CalDateTime::DateTime(datetime) => {
@@ -342,7 +330,6 @@ impl Datelike for CalDateTime {
CalDateTime::Date(date) => Some(Self::Date(date.with_ordinal(ordinal)?)), CalDateTime::Date(date) => Some(Self::Date(date.with_ordinal(ordinal)?)),
} }
} }
fn with_ordinal0(&self, ordinal0: u32) -> Option<Self> { fn with_ordinal0(&self, ordinal0: u32) -> Option<Self> {
match &self { match &self {
CalDateTime::DateTime(datetime) => { CalDateTime::DateTime(datetime) => {