Fix DTSTART date when exporting `diary-float'

Instead of using current date as DTSTART and then excluding it
when it doesn't match the `diary-float' rule, just use the first
date which matches the rule in `icalendar-recurring-start-year'.
* lisp/calendar/icalendar.el (icalendar--convert-float-to-ical):
Compute the correct date.
* test/lisp/calendar/icalendar-tests.el: Add a test for the
reported test case.  (Bug#78085)
This commit is contained in:
Richard Lawrence 2025-05-11 07:47:42 +02:00 committed by Eli Zaretskii
parent 3b2b0424cf
commit c1153963b5
2 changed files with 34 additions and 21 deletions

View file

@ -1766,10 +1766,19 @@ entries. ENTRY-MAIN is the first line of the diary entry."
;matching, esp. with
;different forms of
;MONTH
(month (nth 1 sexp))
(month-exp (nth 1 sexp))
(months (cond ((eq month-exp t) nil) ; don't add a BYMONTH clause
((integerp month-exp) (list month-exp))
(t month-exp)))
(dayname (nth 2 sexp))
(n (nth 3 sexp))
(day (nth 4 sexp))
(dtstart
;; Start on the first day matching the rule in
;; icalendar-recurring-start-year:
(calendar-nth-named-day n dayname
(if months (apply #'min months) 1)
icalendar-recurring-start-year))
(summary
(replace-regexp-in-string
"\\(^\s+\\|\s+$\\)" ""
@ -1781,31 +1790,19 @@ entries. ENTRY-MAIN is the first line of the diary entry."
(error "Don't know if or how to implement day in `diary-float'")))
(cons (concat
;;Start today (yes this is an arbitrary choice):
"\nDTSTART;VALUE=DATE:"
(format-time-string "%Y%m%d")
;;BUT remove today if `diary-float'
;;expression does not hold true for today:
(when
(null (calendar-dlet ((date (calendar-current-date))
(entry entry-main))
(diary-float month dayname n)))
(concat
"\nEXDATE;VALUE=DATE:"
(format-time-string "%Y%m%d")))
(format "%04d%02d%02d"
(calendar-extract-year dtstart)
(calendar-extract-month dtstart)
(calendar-extract-day dtstart))
"\nRRULE:"
(if (or (numberp month) (listp month))
(if months
"FREQ=YEARLY;BYMONTH="
"FREQ=MONTHLY")
(when
(listp month)
(when months
(mapconcat
(lambda (m)
(number-to-string m))
(cadr month) ","))
(when
(numberp month)
(number-to-string month))
(lambda (m) (number-to-string m))
months ","))
";BYDAY="
(number-to-string n)
(aref icalendar--weekday-array dayname))

View file

@ -132,6 +132,22 @@
(car result)))
(should (string= "Sommerferien" (cdr result)))))
(ert-deftest icalendar--convert-float-to-ical ()
"Test method for `icalendar--convert-float-to-ical'."
;; See Bug#78085
(let* ((calendar-date-style 'iso)
(icalendar-recurring-start-year 2025)
(first-saturday-date "20250104") ; first Sat. in 2025
result)
(setq result (icalendar--convert-float-to-ical
"" "%%(diary-float t 6 1) 1st Sat/month"))
(should (consp result))
(should (string= (concat
"\nDTSTART;VALUE=DATE:" first-saturday-date
"\nRRULE:FREQ=MONTHLY;BYDAY=1SA")
(car result)))
(should (string= "1st Sat/month" (cdr result)))))
(ert-deftest icalendar--convert-yearly-to-ical ()
"Test method for `icalendar--convert-yearly-to-ical'."
(let* ((calendar-date-style 'iso)