Interviews: an unknown time zone, a floating time or an all-day event is read as UTC and moves the interview #24

Closed
opened 2026-10-01 10:47:53 +00:00 by tiagoagueda · 1 comment
Owner

Found on 2026-09-29 in a read-only review of postulo-dav at 97abc9779, reading the iCalendar time parser and running it on sample events.

parse_moment turns DTSTART and DTEND into UTC, and three kinds of value come out wrong. A TZID that zoneinfo cannot load (a Windows zone name such as W. Europe Standard Time, or a client's own VTIMEZONE id) silently becomes UTC, and the VTIMEZONE in the same document is never read. A floating time, which RFC 5545 §3.3.5 defines as local time, is taken as UTC. A date-only DTSTART becomes midnight UTC. apply_event hands the result straight to reschedule_interview, which moves the interview, writes "moved from … to …" on the timeline and moves the reminder.

  • Where: src/postulo_dav/text.py:286-303 (parse_moment: zone = dt.UTC … except Exception: zone = dt.UTC, and return dt.datetime(y, mo, d, tzinfo=dt.UTC) for a date); src/postulo_dav/sync.py:194-197 (apply_event calls reschedule_interview whenever both ends parsed).
  • What happens: a calendar client that writes Windows zone names saves DTSTART;TZID=W. Europe Standard Time:20260910T140000. The parser returns 14:00 UTC (checked by running text_to_events), so a 14:00 Berlin interview is moved to 16:00 Berlin time here, with a timeline entry and a moved reminder. DTSTART:20260910T140000 (floating) also gives 14:00 UTC. Turning the event into an all-day event on the phone reschedules the interview to 00:00 UTC for 24 hours. The existing test test_an_event_is_read_with_its_zone_and_recurrence_noticed asserts the date-only result as intended.
  • Why it matters: an interview's time is the thing the person must not get wrong, and the wrong one arrives with a timeline entry that looks authoritative.
  • Fix: when a TZID does not load, try a Windows-to-IANA mapping (the CLDR windowsZones table) and then the VTIMEZONE in the same document; if none resolves, return None so the pull does not reschedule, and add a report note naming the event. Do not reschedule from a floating or date-only DTSTART; report it as a note instead.

Done when

  • Tests in tests/test_dav.py that pull an event with an unresolvable TZID, a floating DTSTART and a date-only DTSTART, and assert the interview's time is unchanged and the report carries a note; and a parser test that a Windows zone name resolves to the right UTC instant.
Found on 2026-09-29 in a read-only review of postulo-dav at 97abc9779, reading the iCalendar time parser and running it on sample events. `parse_moment` turns DTSTART and DTEND into UTC, and three kinds of value come out wrong. A TZID that `zoneinfo` cannot load (a Windows zone name such as `W. Europe Standard Time`, or a client's own VTIMEZONE id) silently becomes UTC, and the VTIMEZONE in the same document is never read. A floating time, which RFC 5545 §3.3.5 defines as local time, is taken as UTC. A date-only DTSTART becomes midnight UTC. `apply_event` hands the result straight to `reschedule_interview`, which moves the interview, writes "moved from … to …" on the timeline and moves the reminder. - **Where:** `src/postulo_dav/text.py:286-303` (`parse_moment`: `zone = dt.UTC` … `except Exception: zone = dt.UTC`, and `return dt.datetime(y, mo, d, tzinfo=dt.UTC)` for a date); `src/postulo_dav/sync.py:194-197` (`apply_event` calls `reschedule_interview` whenever both ends parsed). - **What happens:** a calendar client that writes Windows zone names saves `DTSTART;TZID=W. Europe Standard Time:20260910T140000`. The parser returns 14:00 UTC (checked by running `text_to_events`), so a 14:00 Berlin interview is moved to 16:00 Berlin time here, with a timeline entry and a moved reminder. `DTSTART:20260910T140000` (floating) also gives 14:00 UTC. Turning the event into an all-day event on the phone reschedules the interview to 00:00 UTC for 24 hours. The existing test `test_an_event_is_read_with_its_zone_and_recurrence_noticed` asserts the date-only result as intended. - **Why it matters:** an interview's time is the thing the person must not get wrong, and the wrong one arrives with a timeline entry that looks authoritative. - **Fix:** when a TZID does not load, try a Windows-to-IANA mapping (the CLDR `windowsZones` table) and then the VTIMEZONE in the same document; if none resolves, return `None` so the pull does not reschedule, and add a report note naming the event. Do not reschedule from a floating or date-only DTSTART; report it as a note instead. ## Done when - Tests in `tests/test_dav.py` that pull an event with an unresolvable TZID, a floating DTSTART and a date-only DTSTART, and assert the interview's time is unchanged and the report carries a note; and a parser test that a Windows zone name resolves to the right UTC instant.
tiagoagueda added this to the 0.6.0 milestone 2026-10-01 10:47:53 +00:00
Author
Owner

Fixed by pull request #35, merged as fb8bbd7ae.

Fixed by pull request #35, merged as fb8bbd7ae.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Postulo/postulo-dav#24
No description provided.