229 lines
5.1 KiB
Rust
229 lines
5.1 KiB
Rust
use super::*;
|
|
|
|
fn chicago_time(
|
|
year: i32,
|
|
month: u32,
|
|
day: u32,
|
|
hour: u32,
|
|
minute: u32,
|
|
second: u32,
|
|
) -> DateTime<chrono_tz::Tz> {
|
|
chrono_tz::America::Chicago
|
|
.with_ymd_and_hms(year, month, day, hour, minute, second)
|
|
.unwrap()
|
|
}
|
|
|
|
fn dt_from_ts(ts: i64) -> DateTime<chrono_tz::Tz> {
|
|
DateTime::from_timestamp(ts, 0)
|
|
.unwrap()
|
|
.with_timezone(&chrono_tz::America::Chicago)
|
|
}
|
|
|
|
/// Expect that parsing a calendar works
|
|
#[test]
|
|
fn calendar_from_str() -> Result<()> {
|
|
// Blank lines added for clarity
|
|
let s = r#"
|
|
BEGIN:VCALENDAR
|
|
|
|
CALSCALE:GREGORIAN
|
|
X-WR-TIMEZONE:America/Chicago
|
|
|
|
BEGIN:VTIMEZONE
|
|
TZID:America/Chicago
|
|
X-LIC-LOCATION:America/Chicago
|
|
BEGIN:DAYLIGHT
|
|
TZOFFSETFROM:-0600
|
|
TZOFFSETTO:-0500
|
|
TZNAME:CDT
|
|
DTSTART:19700308T020000
|
|
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
|
|
END:DAYLIGHT
|
|
BEGIN:STANDARD
|
|
TZOFFSETFROM:-0500
|
|
TZOFFSETTO:-0600
|
|
TZNAME:CST
|
|
DTSTART:19701101T020000
|
|
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
|
|
END:STANDARD
|
|
END:VTIMEZONE
|
|
|
|
BEGIN:VEVENT
|
|
DTSTART;TZID=America/Chicago:20250908T180000
|
|
DTEND;TZID=America/Chicago:20250908T200000
|
|
UID:Redacted
|
|
RECURRENCE-ID;TZID=America/Chicago:20250901T180000
|
|
CREATED:20241222T171032Z
|
|
LAST-MODIFIED:20250812T021726Z
|
|
SEQUENCE:1
|
|
STATUS:CONFIRMED
|
|
SUMMARY:zero roman mummy hatch
|
|
TRANSP:OPAQUE
|
|
END:VEVENT
|
|
|
|
END:VCALENDAR
|
|
"#;
|
|
|
|
let ical = ICal::read_from_str(s)?;
|
|
let now = dt_from_ts(1755000000);
|
|
let params = Parameters::new(now)?;
|
|
let instances = ical.event_instances(¶ms)?;
|
|
assert_eq!(instances.len(), 1);
|
|
|
|
let event = &instances[0];
|
|
let expected_time = DatePerhapsTime {
|
|
dt: chicago_time(2025, 9, 8, 18, 0, 0),
|
|
all_day: false,
|
|
};
|
|
assert_eq!(event.dtstart, expected_time);
|
|
assert_eq!(event.ev.get_summary(), Some("zero roman mummy hatch"));
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn hand_written() -> Result<()> {
|
|
let s = r#"
|
|
BEGIN:VCALENDAR
|
|
|
|
COMMENT:August
|
|
|
|
BEGIN:VEVENT
|
|
DTSTART;TZID=America/Chicago:20250819T210000
|
|
DTEND;TZID=America/Chicago:20250819T223000
|
|
SUMMARY:Redacted
|
|
END:VEVENT
|
|
|
|
BEGIN:VEVENT
|
|
DTSTART;TZID=America/Chicago:20250823T170000
|
|
SUMMARY:Redacted
|
|
URL:https://www.example.com
|
|
END:VEVENT
|
|
|
|
END:VCALENDAR
|
|
"#;
|
|
|
|
let ical = ICal::read_from_str(s)?;
|
|
let params = Parameters {
|
|
ignore_before: chicago_time(2025, 1, 1, 0, 0, 0),
|
|
output_start: chicago_time(2025, 7, 1, 0, 0, 0),
|
|
output_stop: chicago_time(2025, 10, 1, 0, 0, 0),
|
|
tz: chrono_tz::America::Chicago,
|
|
};
|
|
let instances = ical.event_instances(¶ms)?;
|
|
|
|
assert_eq!(
|
|
[instances[0].dtstart, instances[1].dtstart,],
|
|
[
|
|
DatePerhapsTime {
|
|
dt: chicago_time(2025, 8, 19, 21, 0, 0),
|
|
all_day: false,
|
|
},
|
|
DatePerhapsTime {
|
|
dt: chicago_time(2025, 8, 23, 17, 0, 0),
|
|
all_day: false,
|
|
},
|
|
]
|
|
);
|
|
assert_eq!(instances.len(), 2);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Expect that recurrent exceptions work correctly and don't duplicate events
|
|
#[test]
|
|
fn recurrence_exceptions() -> Result<()> {
|
|
let s = r#"
|
|
BEGIN:VCALENDAR
|
|
|
|
CALSCALE:GREGORIAN
|
|
X-WR-TIMEZONE:America/Chicago
|
|
|
|
BEGIN:VTIMEZONE
|
|
TZID:America/Chicago
|
|
X-LIC-LOCATION:America/Chicago
|
|
BEGIN:DAYLIGHT
|
|
TZOFFSETFROM:-0600
|
|
TZOFFSETTO:-0500
|
|
TZNAME:CDT
|
|
DTSTART:19700308T020000
|
|
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
|
|
END:DAYLIGHT
|
|
BEGIN:STANDARD
|
|
TZOFFSETFROM:-0500
|
|
TZOFFSETTO:-0600
|
|
TZNAME:CST
|
|
DTSTART:19701101T020000
|
|
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
|
|
END:STANDARD
|
|
END:VTIMEZONE
|
|
|
|
BEGIN:VEVENT
|
|
DTSTART;TZID=America/Chicago:20250708T180000
|
|
DTEND;TZID=America/Chicago:20250708T200000
|
|
RRULE:FREQ=MONTHLY;BYDAY=2TU
|
|
UID:jazz repay stout steam
|
|
CLASS:PUBLIC
|
|
CREATED:20250703T113806Z
|
|
LAST-MODIFIED:20250721T232331Z
|
|
SEQUENCE:1
|
|
STATUS:CONFIRMED
|
|
SUMMARY:coil perm brush zippy
|
|
TRANSP:OPAQUE
|
|
END:VEVENT
|
|
|
|
BEGIN:VEVENT
|
|
DTSTART;TZID=America/Chicago:20250814T180000
|
|
DTEND;TZID=America/Chicago:20250814T200000
|
|
UID:jazz repay stout steam
|
|
RECURRENCE-ID;TZID=America/Chicago:20250812T180000
|
|
CLASS:PUBLIC
|
|
CREATED:20250703T113806Z
|
|
LAST-MODIFIED:20250721T232500Z
|
|
SEQUENCE:2
|
|
STATUS:CONFIRMED
|
|
SUMMARY:coil perm brush zippy
|
|
TRANSP:OPAQUE
|
|
END:VEVENT
|
|
|
|
END:VCALENDAR
|
|
"#;
|
|
|
|
let ical = ICal::read_from_str(s)?;
|
|
let params = Parameters {
|
|
ignore_before: chicago_time(2025, 1, 1, 0, 0, 0),
|
|
output_start: chicago_time(2025, 7, 1, 0, 0, 0),
|
|
output_stop: chicago_time(2025, 10, 1, 0, 0, 0),
|
|
tz: chrono_tz::America::Chicago,
|
|
};
|
|
let instances = ical.event_instances(¶ms)?;
|
|
|
|
assert_eq!(
|
|
[
|
|
instances[0].dtstart,
|
|
instances[1].dtstart,
|
|
instances[2].dtstart,
|
|
],
|
|
[
|
|
DatePerhapsTime {
|
|
dt: chicago_time(2025, 7, 8, 18, 0, 0),
|
|
all_day: false,
|
|
},
|
|
DatePerhapsTime {
|
|
dt: chicago_time(2025, 9, 9, 18, 0, 0),
|
|
all_day: false,
|
|
},
|
|
DatePerhapsTime {
|
|
dt: chicago_time(2025, 8, 14, 18, 0, 0),
|
|
all_day: false,
|
|
},
|
|
]
|
|
);
|
|
|
|
for instance in &instances {
|
|
assert_eq!(instance.ev.get_summary(), Some("coil perm brush zippy"));
|
|
}
|
|
|
|
assert_eq!(instances.len(), 3);
|
|
|
|
Ok(())
|
|
}
|