From 2a4ba33e454e1df1bec646bfcf7a49c586ecb0a5 Mon Sep 17 00:00:00 2001 From: Lennart K <18233294+lennart-k@users.noreply.github.com> Date: Thu, 18 Dec 2025 21:27:40 +0100 Subject: [PATCH] refactor recurrence expansion --- crates/ical/src/icalendar/event.rs | 154 ++++++++++++++--------------- 1 file changed, 77 insertions(+), 77 deletions(-) diff --git a/crates/ical/src/icalendar/event.rs b/crates/ical/src/icalendar/event.rs index cdf135e..9449554 100644 --- a/crates/ical/src/icalendar/event.rs +++ b/crates/ical/src/icalendar/event.rs @@ -99,85 +99,85 @@ impl EventObject { end: Option>, overrides: &[Self], ) -> Result, Error> { - if let Some(mut rrule_set) = self.recurrence_ruleset()? { - if let Some(start) = start { - rrule_set = rrule_set.after(start.with_timezone(&rrule::Tz::UTC)); - } - if let Some(end) = end { - rrule_set = rrule_set.before(end.with_timezone(&rrule::Tz::UTC)); - } - let mut events = vec![]; - let dates = rrule_set.all(2048).dates; - let dtstart = self.get_dtstart()?.expect("We must have a DTSTART here"); - let computed_duration = self - .get_dtend()? - .map(|dtend| dtend.as_datetime().into_owned() - dtstart.as_datetime().into_owned()); + let Some(mut rrule_set) = self.recurrence_ruleset()? else { + return Ok(vec![self.event.clone()]); + }; - 'recurrence: for date in dates { - let date = CalDateTime::from(date); - let dateformat = if dtstart.is_date() { - date.format_date() - } else { - date.format() - }; - - for ev_override in overrides { - if let Some(override_id) = &ev_override - .event - .get_recurrence_id() - .as_ref() - .expect("overrides have a recurrence id") - .value - && override_id == &dateformat - { - // We have an override for this occurence - // - events.push(ev_override.event.clone()); - continue 'recurrence; - } - } - - let mut ev = self.event.clone().mutable(); - ev.remove_property("RRULE"); - ev.remove_property("RDATE"); - ev.remove_property("EXDATE"); - ev.remove_property("EXRULE"); - let dtstart_prop = ev - .get_property("DTSTART") - .expect("We must have a DTSTART here") - .clone(); - ev.remove_property("DTSTART"); - ev.remove_property("DTEND"); - - ev.set_property(Property { - name: "RECURRENCE-ID".to_string(), - value: Some(dateformat.clone()), - params: vec![], - }); - ev.set_property(Property { - name: "DTSTART".to_string(), - value: Some(dateformat), - params: dtstart_prop.params.clone(), - }); - if let Some(duration) = computed_duration { - let dtend = date + duration; - let dtendformat = if dtstart.is_date() { - dtend.format_date() - } else { - dtend.format() - }; - ev.set_property(Property { - name: "DTEND".to_string(), - value: Some(dtendformat), - params: dtstart_prop.params, - }); - } - events.push(ev.verify()?); - } - Ok(events) - } else { - Ok(vec![self.event.clone()]) + if let Some(start) = start { + rrule_set = rrule_set.after(start.with_timezone(&rrule::Tz::UTC)); } + if let Some(end) = end { + rrule_set = rrule_set.before(end.with_timezone(&rrule::Tz::UTC)); + } + let mut events = vec![]; + let dates = rrule_set.all(2048).dates; + let dtstart = self.get_dtstart()?.expect("We must have a DTSTART here"); + let computed_duration = self + .get_dtend()? + .map(|dtend| dtend.as_datetime().into_owned() - dtstart.as_datetime().as_ref()); + + 'recurrence: for date in dates { + let date = CalDateTime::from(date); + let dateformat = if dtstart.is_date() { + date.format_date() + } else { + date.format() + }; + + for ev_override in overrides { + if let Some(override_id) = &ev_override + .event + .get_recurrence_id() + .as_ref() + .expect("overrides have a recurrence id") + .value + && override_id == &dateformat + { + // We have an override for this occurence + // + events.push(ev_override.event.clone()); + continue 'recurrence; + } + } + + let mut ev = self.event.clone().mutable(); + ev.remove_property("RRULE"); + ev.remove_property("RDATE"); + ev.remove_property("EXDATE"); + ev.remove_property("EXRULE"); + let dtstart_prop = ev + .get_property("DTSTART") + .expect("We must have a DTSTART here") + .clone(); + ev.remove_property("DTSTART"); + ev.remove_property("DTEND"); + + ev.set_property(Property { + name: "RECURRENCE-ID".to_string(), + value: Some(dateformat.clone()), + params: vec![], + }); + ev.set_property(Property { + name: "DTSTART".to_string(), + value: Some(dateformat), + params: dtstart_prop.params.clone(), + }); + if let Some(duration) = computed_duration { + let dtend = date + duration; + let dtendformat = if dtstart.is_date() { + dtend.format_date() + } else { + dtend.format() + }; + ev.set_property(Property { + name: "DTEND".to_string(), + value: Some(dtendformat), + params: dtstart_prop.params, + }); + } + events.push(ev.verify()?); + } + Ok(events) } }