aboutsummaryrefslogtreecommitdiff
path: root/tests/test-calendar-sync--expand-yearly.el
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-07-18 12:57:32 -0500
committerCraig Jennings <c@cjennings.net>2026-07-18 12:57:32 -0500
commitb426cd089503053fd203a034f3cbbe173252d5c3 (patch)
tree583c679fb3daa94445efd818313ce0805c6abdbc /tests/test-calendar-sync--expand-yearly.el
parentb5a7ac309217a1aeece1c043cf29002cfea6c9ef (diff)
downloaddotemacs-b426cd089503053fd203a034f3cbbe173252d5c3.tar.gz
dotemacs-b426cd089503053fd203a034f3cbbe173252d5c3.zip
fix(calendar-sync): honor BYDAY rules and drop cancelled events
The expander ignored BYDAY on monthly and yearly rules and stepped DTSTART's day-of-month instead, so a "2nd Wednesday" series rendered on the 12th of every month, the wrong weekday most months. It now resolves nth-weekday entries (2WE, -1TU), bare weekdays with BYSETPOS, and yearly BYMONTH+BYDAY, so each occurrence lands on the day the rule names. Nothing read the VEVENT STATUS property, so cancelled events rendered as normal meetings: a cancelled instance of a series reappeared at its original time, and standalone cancelled events stayed on the agenda. parse-event now drops STATUS:CANCELLED events, which also kills cancelled series masters. A cancelled RECURRENCE-ID override removes its occurrence instead of overriding it. The fixes are coupled: until BYDAY generates the right dates, a cancelled override can't match the occurrence it removes.
Diffstat (limited to 'tests/test-calendar-sync--expand-yearly.el')
-rw-r--r--tests/test-calendar-sync--expand-yearly.el26
1 files changed, 26 insertions, 0 deletions
diff --git a/tests/test-calendar-sync--expand-yearly.el b/tests/test-calendar-sync--expand-yearly.el
index ad9b8f27..c636e54a 100644
--- a/tests/test-calendar-sync--expand-yearly.el
+++ b/tests/test-calendar-sync--expand-yearly.el
@@ -175,5 +175,31 @@
(occurrences (calendar-sync--expand-yearly base-event rrule range)))
(should (= (length occurrences) 2))))
+;;; BYMONTH + BYDAY (nth weekday) Cases
+;;
+;; Fixed dates are deterministic here: the expansion range is an explicit
+;; parameter, not derived from the current time.
+
+(ert-deftest test-calendar-sync--expand-yearly-bymonth-byday-nth-weekday ()
+ "Normal: FREQ=YEARLY;BYMONTH=3;BYDAY=2SU tracks the 2nd Sunday of March
+each year (the DST clock-change shape), not DTSTART's calendar date."
+ (let* ((base-event (list :summary "Clocks change"
+ :start '(2026 3 8 2 0)
+ :end '(2026 3 8 3 0)))
+ (rrule (list :freq 'yearly :interval 1 :bymonth 3 :byday '("2SU")))
+ (range (list (encode-time 0 0 0 1 1 2026)
+ (encode-time 0 0 0 31 12 2027)))
+ (occurrences (calendar-sync--expand-yearly base-event rrule range))
+ (days (mapcar (lambda (occ)
+ (let ((s (plist-get occ :start)))
+ (list (nth 0 s) (nth 1 s) (nth 2 s))))
+ occurrences)))
+ ;; 2nd Sunday of March: 2026-03-08, 2027-03-14 -- different day-of-month.
+ (should (equal days '((2026 3 8) (2027 3 14))))
+ (dolist (occ occurrences)
+ (let ((s (plist-get occ :start)))
+ (should (= 7 (calendar-sync--date-weekday
+ (list (nth 0 s) (nth 1 s) (nth 2 s)))))))))
+
(provide 'test-calendar-sync--expand-yearly)
;;; test-calendar-sync--expand-yearly.el ends here