Commit9a3e6029Recorded17 Mar 2026Repositorysigil-caldav
Handle local timezone in iCalendar datetime parsing
Message
parse-ical-datetime now distinguishes UTC times (Z suffix) from local times (no suffix, used with TZID parameter). Local times are adjusted by the system's UTC offset to produce the correct Unix timestamp. Previously all times were treated as UTC, causing events with timezone info to display at the wrong time.
Changed
src/sigil/caldav/ical.sgl | 30 ++++++++++++++++++------------
1 file changed, 18 insertions(+), 12 deletions(-)Diff
src/sigil/caldav/ical.sglmodified
@@ -9,7 +9,8 @@
9
(sigil math) 10
(sigil string) 11
(sigil struct)−12
(sigil crypto))+12
(sigil crypto)+13
(sigil time)) 14
15
(export 16
;; Event struct@@ -125,22 +126,27 @@
126
127
;;; Parse an iCalendar datetime string to a Unix timestamp. 128
;;;−128
;;; Supports both UTC datetimes (with Z suffix) and local datetimes.−129
;;; Local datetimes are interpreted as UTC.+129
;;; UTC datetimes (Z suffix) are interpreted as UTC.+130
;;; Local datetimes (no Z) are interpreted in the system timezone. 131
;;; 132
;;; ```scheme−132
;;; (parse-ical-datetime "20240315T090000Z") ; => 1710493200−133
;;; (parse-ical-datetime "20240315T090000") ; => 1710493200+133
;;; (parse-ical-datetime "20240315T090000Z") ; => UTC 09:00+134
;;; (parse-ical-datetime "20240315T090000") ; => local 09:00 135
;;; ``` 136
(define (parse-ical-datetime str) 137
(: string? -> number?)−137
(let ((y (string->number (substring str 0 4)))−138
(mo (string->number (substring str 4 6)))−139
(d (string->number (substring str 6 8)))−140
(h (string->number (substring str 9 11)))−141
(mi (string->number (substring str 11 13)))−142
(s (string->number (substring str 13 15))))−143
(utc->timestamp y mo d h mi s)))+138
(let* ((utc? (string-ends-with? str "Z"))+139
(y (string->number (substring str 0 4)))+140
(mo (string->number (substring str 4 6)))+141
(d (string->number (substring str 6 8)))+142
(h (string->number (substring str 9 11)))+143
(mi (string->number (substring str 11 13)))+144
(s (string->number (substring str 13 15)))+145
(ts (utc->timestamp y mo d h mi s)))+146
(if utc?+147
ts+148
;; Local time: subtract UTC offset to get the correct Unix timestamp+149
(- ts (time-utc-offset))))) 150
151
;;; Parse an iCalendar date string to a Unix timestamp. 152
;;;