diff --git a/crates/store/src/calendar/ical.rs b/crates/store/src/calendar/ical.rs new file mode 100644 index 0000000..bb89e5e --- /dev/null +++ b/crates/store/src/calendar/ical.rs @@ -0,0 +1,25 @@ +pub trait IcalProperty { + fn get_param(&self, name: &str) -> Option>; + fn get_value_type(&self) -> Option<&str>; + fn get_tzid(&self) -> Option<&str>; +} + +impl IcalProperty for ical::property::Property { + fn get_param(&self, name: &str) -> Option> { + self.params + .as_ref()? + .iter() + .find(|(key, _)| name == key) + .map(|(_, value)| value.iter().map(String::as_str).collect()) + } + + fn get_value_type(&self) -> Option<&str> { + self.get_param("VALUE") + .and_then(|params| params.into_iter().next()) + } + + fn get_tzid(&self) -> Option<&str> { + self.get_param("TZID") + .and_then(|params| params.into_iter().next()) + } +} diff --git a/crates/store/src/calendar/mod.rs b/crates/store/src/calendar/mod.rs index a61feee..037e00f 100644 --- a/crates/store/src/calendar/mod.rs +++ b/crates/store/src/calendar/mod.rs @@ -1,5 +1,6 @@ mod calendar; mod event; +mod ical; mod journal; mod object; mod rrule; @@ -8,6 +9,7 @@ mod todo; pub use calendar::*; pub use event::*; +pub use ical::*; pub use journal::*; pub use object::*; pub use timestamp::*; diff --git a/crates/store/src/calendar/timestamp.rs b/crates/store/src/calendar/timestamp.rs index 4f02e80..8f94de5 100644 --- a/crates/store/src/calendar/timestamp.rs +++ b/crates/store/src/calendar/timestamp.rs @@ -3,13 +3,15 @@ use chrono::{DateTime, Duration, NaiveDate, NaiveDateTime, NaiveTime, Utc}; use chrono_tz::Tz; use derive_more::derive::Deref; use ical::{ - parser::{ical::component::IcalTimeZone, Component}, + parser::{Component, ical::component::IcalTimeZone}, property::Property, }; use lazy_static::lazy_static; use rustical_xml::{ValueDeserialize, ValueSerialize}; use std::{collections::HashMap, ops::Add}; +use super::IcalProperty; + lazy_static! { static ref RE_DURATION: regex::Regex = regex::Regex::new(r"^(?[+-])?P((?P\d+)W)?((?P\d+)D)?(T((?P\d+)H)?((?P\d+)M)?((?P\d+)S)?)?$").unwrap(); @@ -74,24 +76,15 @@ impl CalDateTime { prop: &Property, timezones: &HashMap, ) -> Result, Error> { - let prop_value = if let Some(value) = &prop.value { - value.to_owned() + let prop_value = if let Some(value) = prop.value.as_ref() { + value } else { return Ok(None); }; // Use the TZID parameter from the property - let timezone = if let Some(tzid) = &prop - .params - .clone() - .unwrap_or_default() - .iter() - .filter(|(name, _values)| name == "TZID") - .map(|(_name, values)| values.first()) - .next() - .unwrap_or_default() - { - if let Some(timezone) = timezones.get(tzid.to_owned()) { + let timezone = if let Some(tzid) = prop.get_tzid() { + if let Some(timezone) = timezones.get(tzid) { // X-LIC-LOCATION is often used to refer to a standardised timezone from the Olson // database if let Some(olson_name) = timezone @@ -109,13 +102,9 @@ impl CalDateTime { } else { // If the TZID matches a name from the Olson database (e.g. Europe/Berlin) we // guess that we can just use it - if let Ok(tz) = tzid.parse::() { - Some(tz) - } else { - // TODO: Too bad, we need to manually parse it - // For now it's just treated as localtime - None - } + tzid.parse::().ok() + // TODO: If None: Too bad, we need to manually parse it + // For now it's just treated as localtime } } else { // TZID refers to timezone that does not exist @@ -129,7 +118,7 @@ impl CalDateTime { None }; - Self::parse(&prop_value, timezone).map(Some) + Self::parse(prop_value, timezone).map(Some) } pub fn format(&self) -> String {