aboutsummaryrefslogtreecommitdiff
path: root/aero-ical/src/parser.rs
diff options
context:
space:
mode:
authorQuentin Dufour <quentin@deuxfleurs.fr>2024-05-26 10:33:04 +0200
committerQuentin Dufour <quentin@deuxfleurs.fr>2024-05-26 10:33:04 +0200
commit6b9720844aaa86ad25a77c0821dcdbc772937065 (patch)
tree50559b9131be478d6907474e0f612e903ba44d34 /aero-ical/src/parser.rs
parent52f870633c2cab8a4aeeec74792774931139b8b5 (diff)
downloadaerogramme-6b9720844aaa86ad25a77c0821dcdbc772937065.tar.gz
aerogramme-6b9720844aaa86ad25a77c0821dcdbc772937065.zip
better support for time-range
Diffstat (limited to 'aero-ical/src/parser.rs')
-rw-r--r--aero-ical/src/parser.rs100
1 files changed, 54 insertions, 46 deletions
diff --git a/aero-ical/src/parser.rs b/aero-ical/src/parser.rs
index 4354737..ca271a5 100644
--- a/aero-ical/src/parser.rs
+++ b/aero-ical/src/parser.rs
@@ -1,11 +1,11 @@
use chrono::TimeDelta;
-use nom::IResult;
use nom::branch::alt;
use nom::bytes::complete::{tag, tag_no_case};
-use nom::combinator::{value, opt, map, map_opt};
-use nom::sequence::{pair, tuple};
use nom::character::complete as nomchar;
+use nom::combinator::{map, map_opt, opt, value};
+use nom::sequence::{pair, tuple};
+use nom::IResult;
use aero_dav::caltypes as cal;
@@ -19,10 +19,13 @@ pub fn date_time(dt: &str) -> Option<chrono::DateTime<chrono::Utc>> {
let tmpl = match dt.chars().last() {
Some('Z') => cal::UTC_DATETIME_FMT,
Some(_) => {
- tracing::warn!(raw_time=dt, "floating datetime is not properly supported yet");
+ tracing::warn!(
+ raw_time = dt,
+ "floating datetime is not properly supported yet"
+ );
cal::FLOATING_DATETIME_FMT
- },
- None => return None
+ }
+ None => return None,
};
chrono::NaiveDateTime::parse_from_str(dt, tmpl)
@@ -43,46 +46,58 @@ pub fn date_time(dt: &str) -> Option<chrono::DateTime<chrono::Utc>> {
/// dur-day = 1*DIGIT "D"
/// ```
pub fn dur_value(text: &str) -> IResult<&str, TimeDelta> {
- map_opt(tuple((
- dur_sign,
- tag_no_case("P"),
- alt((
- dur_date,
- dur_time,
- dur_week,
- ))
- )), |(sign, _, delta)| {
- delta.checked_mul(sign)
- })(text)
+ map_opt(
+ tuple((
+ dur_sign,
+ tag_no_case("P"),
+ alt((dur_date, dur_time, dur_week)),
+ )),
+ |(sign, _, delta)| delta.checked_mul(sign),
+ )(text)
}
fn dur_sign(text: &str) -> IResult<&str, i32> {
- map(opt(alt((value(1, tag("+")), value(-1, tag("-"))))), |x| x.unwrap_or(1))(text)
+ map(opt(alt((value(1, tag("+")), value(-1, tag("-"))))), |x| {
+ x.unwrap_or(1)
+ })(text)
}
fn dur_date(text: &str) -> IResult<&str, TimeDelta> {
- map(pair(dur_day, opt(dur_time)), |(day, time)| day + time.unwrap_or(TimeDelta::zero()))(text)
+ map(pair(dur_day, opt(dur_time)), |(day, time)| {
+ day + time.unwrap_or(TimeDelta::zero())
+ })(text)
}
fn dur_time(text: &str) -> IResult<&str, TimeDelta> {
- map(pair(tag_no_case("T"), alt((dur_hour, dur_minute, dur_second))), |(_, x)| x)(text)
+ map(
+ pair(tag_no_case("T"), alt((dur_hour, dur_minute, dur_second))),
+ |(_, x)| x,
+ )(text)
}
fn dur_week(text: &str) -> IResult<&str, TimeDelta> {
- map_opt(pair(nomchar::i64, tag_no_case("W")), |(i, _)| TimeDelta::try_weeks(i))(text)
+ map_opt(pair(nomchar::i64, tag_no_case("W")), |(i, _)| {
+ TimeDelta::try_weeks(i)
+ })(text)
}
fn dur_day(text: &str) -> IResult<&str, TimeDelta> {
- map_opt(pair(nomchar::i64, tag_no_case("D")), |(i, _)| TimeDelta::try_days(i))(text)
+ map_opt(pair(nomchar::i64, tag_no_case("D")), |(i, _)| {
+ TimeDelta::try_days(i)
+ })(text)
}
fn dur_hour(text: &str) -> IResult<&str, TimeDelta> {
- map_opt(tuple((nomchar::i64, tag_no_case("H"), opt(dur_minute))), |(i, _, mm)| {
- TimeDelta::try_hours(i).map(|hours| hours + mm.unwrap_or(TimeDelta::zero()))
- })(text)
+ map_opt(
+ tuple((nomchar::i64, tag_no_case("H"), opt(dur_minute))),
+ |(i, _, mm)| TimeDelta::try_hours(i).map(|hours| hours + mm.unwrap_or(TimeDelta::zero())),
+ )(text)
}
fn dur_minute(text: &str) -> IResult<&str, TimeDelta> {
- map_opt(tuple((nomchar::i64, tag_no_case("M"), opt(dur_second))), |(i, _, ms)| {
- TimeDelta::try_minutes(i).map(|min| min + ms.unwrap_or(TimeDelta::zero()))
- })(text)
+ map_opt(
+ tuple((nomchar::i64, tag_no_case("M"), opt(dur_second))),
+ |(i, _, ms)| TimeDelta::try_minutes(i).map(|min| min + ms.unwrap_or(TimeDelta::zero())),
+ )(text)
}
fn dur_second(text: &str) -> IResult<&str, TimeDelta> {
- map_opt(pair(nomchar::i64, tag_no_case("S")), |(i, _)| TimeDelta::try_seconds(i))(text)
+ map_opt(pair(nomchar::i64, tag_no_case("S")), |(i, _)| {
+ TimeDelta::try_seconds(i)
+ })(text)
}
#[cfg(test)]
@@ -95,8 +110,11 @@ mod tests {
let to_parse = "P15DT5H0M20S";
let (_, time_delta) = dur_value(to_parse).unwrap();
assert_eq!(
- time_delta,
- TimeDelta::try_days(15).unwrap() + TimeDelta::try_hours(5).unwrap() + TimeDelta::try_seconds(20).unwrap());
+ time_delta,
+ TimeDelta::try_days(15).unwrap()
+ + TimeDelta::try_hours(5).unwrap()
+ + TimeDelta::try_seconds(20).unwrap()
+ );
}
#[test]
@@ -104,35 +122,25 @@ mod tests {
// A duration of 7 weeks would be:
let to_parse = "P7W";
let (_, time_delta) = dur_value(to_parse).unwrap();
- assert_eq!(
- time_delta,
- TimeDelta::try_weeks(7).unwrap()
- );
+ assert_eq!(time_delta, TimeDelta::try_weeks(7).unwrap());
}
#[test]
- fn rfc4791_example1() {
+ fn rfc4791_example1() {
// 10 minutes before
let to_parse = "-PT10M";
let (_, time_delta) = dur_value(to_parse).unwrap();
- assert_eq!(
- time_delta,
- TimeDelta::try_minutes(-10).unwrap()
- );
+ assert_eq!(time_delta, TimeDelta::try_minutes(-10).unwrap());
}
-
#[test]
fn ical_org_example1() {
- // The following example is for a "VALARM" calendar component that specifies an email alarm
+ // The following example is for a "VALARM" calendar component that specifies an email alarm
// that will trigger 2 days before the scheduled due DATE-TIME of a to-do with which it is associated.
let to_parse = "-P2D";
let (_, time_delta) = dur_value(to_parse).unwrap();
- assert_eq!(
- time_delta,
- TimeDelta::try_days(-2).unwrap()
- );
+ assert_eq!(time_delta, TimeDelta::try_days(-2).unwrap());
}
}