Fix Calendar: No expanded occurrences are returned for a daily recurrences crossing DST

This commit is contained in:
Maurus Decimus
2026-07-19 22:59:03 +02:00
parent 152db36247
commit 2d08933fbc
4 changed files with 115 additions and 108 deletions

View File

@@ -13,6 +13,7 @@ use groupware::{
calendar::{CalendarEventData, alarm::ExpandAlarm, expand::CalendarEventExpansion},
};
use hyper::StatusCode;
use std::str::FromStr;
use store::write::serialize::rkyv_unarchive;
use types::TimeRange;
@@ -342,6 +343,44 @@ fn roundtrip_expansion(ics: &str, ignore_errors: bool) {
assert_eq!(events, events_archive);
}
#[test]
fn calendar_expand_dst_fallback() {
let akl = Tz::from_str("Pacific/Auckland").unwrap();
let ical = ICalendar::parse(ICAL_DST_FALLBACK_ICS).unwrap();
let event_data = CalendarEventData::new(ical, akl, 1000, &mut None);
let expanded_bytes = rkyv::to_bytes::<rkyv::rancor::Error>(&event_data).unwrap();
let archive = rkyv_unarchive::<CalendarEventData>(&expanded_bytes).unwrap();
let window = archive
.expand(
akl,
TimeRange {
start: 1782777600,
end: 1786579200,
},
)
.unwrap();
assert!(
!window.is_empty(),
"recurrence expansion aborted across the Pacific/Auckland DST fall-back overlap"
);
let across_overlap = archive
.expand(
akl,
TimeRange {
start: 1775260800,
end: 1775433600,
},
)
.unwrap();
assert_eq!(
across_overlap.len(),
1,
"the ambiguous fall-back occurrence must resolve to its earliest instant"
);
}
fn rfc_file_name(num: usize) -> String {
format!(
"{}/john%40example.com/default/abcd{num}.ics",
@@ -823,6 +862,20 @@ END:VFREEBUSY
END:VCALENDAR
"#;
const ICAL_DST_FALLBACK_ICS: &str = r#"BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VEVENT
DTSTAMP:20260108T000000Z
DTSTART;TZID=Pacific/Auckland:20260108T022000
DURATION:PT2H10M
RRULE:FREQ=DAILY;INTERVAL=3
SUMMARY:Auckland DST fall-back recurrence
UID:auckland-dst-fallback@example.com
END:VEVENT
END:VCALENDAR
"#;
const ICAL_RFC_ABCD1_ICS: &str = r#"BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN