From d7bef9bbf6ad41502981466638811e3c8e736111 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Tue, 27 Jan 2026 08:18:43 -0600 Subject: fix(calendar-sync): resolve freeze on DST transitions and large ICS files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two bugs caused Emacs to freeze during calendar sync: 1. split-events used catastrophic regex (\(.\|\n\)*?) on multi-MB ICS data. Replaced with buffer-based search-forward (0.011s for 4.5MB). 2. add-days used midnight for date arithmetic. On DST fall-back days, adding 86400s to midnight CDT yields 11pm CST (same date), creating an infinite loop. Fixed by using noon so ±1h DST shift stays correct. --- modules/calendar-sync.el | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'modules') diff --git a/modules/calendar-sync.el b/modules/calendar-sync.el index 15953ba1..06b5531c 100644 --- a/modules/calendar-sync.el +++ b/modules/calendar-sync.el @@ -278,11 +278,14 @@ Monday = 1, Sunday = 7." (defun calendar-sync--add-days (date days) "Add DAYS to DATE (year month day). -Returns new (year month day)." +Returns new (year month day). +Uses noon internally to avoid DST boundary issues where adding +86400 seconds to midnight can land on the same calendar date +during fall-back transitions." (let* ((year (nth 0 date)) (month (nth 1 date)) (day (nth 2 date)) - (time (encode-time 0 0 0 day month year)) + (time (encode-time 0 0 12 day month year)) (new-time (time-add time (days-to-time days))) (decoded (decode-time new-time))) (list (nth 5 decoded) (nth 4 decoded) (nth 3 decoded)))) @@ -292,11 +295,14 @@ Returns new (year month day)." (defun calendar-sync--split-events (ics-content) "Split ICS-CONTENT into individual VEVENT blocks. Returns list of strings, each containing one VEVENT block." - (let ((events '()) - (start 0)) - (while (string-match "BEGIN:VEVENT\\(.\\|\n\\)*?END:VEVENT" ics-content start) - (push (match-string 0 ics-content) events) - (setq start (match-end 0))) + (let ((events '())) + (with-temp-buffer + (insert ics-content) + (goto-char (point-min)) + (while (search-forward "BEGIN:VEVENT" nil t) + (let ((start (match-beginning 0))) + (when (search-forward "END:VEVENT" nil t) + (push (buffer-substring-no-properties start (point)) events))))) (nreverse events))) (defun calendar-sync--get-property (event property) -- cgit v1.2.3