From: Ulf Jasper Date: Mon, 15 Feb 2021 16:27:45 +0000 (+0100) Subject: Display yearly ical events from first year on. Fix Bug#23100. X-Git-Tag: emacs-28.0.90~3714 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=899619ff6a73cc75880327ad74ec29f072328d79;p=emacs.git Display yearly ical events from first year on. Fix Bug#23100. Convert yearly rrule starting in year x into diary-anniversary entry for year x-1 when importing an icalendar. Correspondingly convert diary-anniversary for year x into yearly rrule starting in year x+1. * test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-american: * test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-european: * test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-iso: * test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-american: * test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-european: * test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-iso: * test/lisp/calendar/icalendar-tests.el (icalendar-convert-anniversary-to-ical): Match new diary-anniversary/yearly-rrule behaviour. * lisp/calendar/icalendar.el (icalendar--datestring-to-isodate): Add year-shift option. (icalendar--convert-anniversary-to-ical): Shift the year as diary-anniversary is not displayed in the initial year. (icalendar--convert-recurring-to-diary): Shift the year as diary-anniversary is not displayed in the initial year. (Bug#23100) --- diff --git a/lisp/calendar/icalendar.el b/lisp/calendar/icalendar.el index 1d7de4a0c5d..dafdd418d0d 100644 --- a/lisp/calendar/icalendar.el +++ b/lisp/calendar/icalendar.el @@ -889,12 +889,14 @@ If DAY-SHIFT is non-nil, the result is shifted by DAY-SHIFT days." (format "%04d%02d%02d" (nth 2 mdy) (nth 0 mdy) (nth 1 mdy)))) -(defun icalendar--datestring-to-isodate (datestring &optional day-shift) +(defun icalendar--datestring-to-isodate (datestring &optional day-shift year-shift) "Convert diary-style DATESTRING to iso-style date. If DAY-SHIFT is non-nil, the result is shifted by DAY-SHIFT days --- DAY-SHIFT must be either nil or an integer. This function -tries to figure the date style from DATESTRING itself. If that -is not possible it uses the current calendar date style." +-- DAY-SHIFT must be either nil or an integer. If YEAR-SHIFT is +non-nil, the result is shifted by YEAR-SHIFT years -- YEAR-SHIFT +must be either nil or an integer. This function tries to figure +the date style from DATESTRING itself. If that is not possible +it uses the current calendar date style." (let ((day -1) month year) (save-match-data (cond ( ;; iso-style numeric date @@ -904,7 +906,7 @@ is not possible it uses the current calendar date style." "0?\\([1-9][0-9]?\\)") datestring) (setq year (read (substring datestring (match-beginning 1) - (match-end 1)))) + (match-end 1)))) (setq month (read (substring datestring (match-beginning 2) (match-end 2)))) (setq day (read (substring datestring (match-beginning 3) @@ -967,6 +969,9 @@ is not possible it uses the current calendar date style." (match-end 3))))) (t nil))) + (when year-shift + (setq year (+ year year-shift))) + (if (> day 0) (let ((mdy (calendar-gregorian-from-absolute (+ (calendar-absolute-from-gregorian (list month day @@ -1916,9 +1921,9 @@ entries. ENTRY-MAIN is the first line of the diary entry." (let* ((datetime (substring entry-main (match-beginning 1) (match-end 1))) (startisostring (icalendar--datestring-to-isodate - datetime)) + datetime nil 1)) (endisostring (icalendar--datestring-to-isodate - datetime 1)) + datetime 1 1)) (starttimestring (icalendar--diarytime-to-isotime (if (match-beginning 3) (substring entry-main @@ -2402,8 +2407,11 @@ END-T is the event's end time in diary format." (if end-t "-" "") (or end-t "")))) (setq result (format - "%%%%(and (diary-anniversary %s)) %s%s%s" - dtstart-conv + "%%%%(diary-anniversary %s) %s%s%s" + (let* ((year (nth 5 dtstart-dec)) + (dtstart-1y-dec (copy-sequence dtstart-dec))) + (setf (nth 5 dtstart-1y-dec) (1- year)) + (icalendar--datetime-to-diary-date dtstart-1y-dec)) (or start-t "") (if end-t "-" "") (or end-t ""))))) ;; monthly diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-american b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-american index 7b86b554dd4..2f7026a0bde 100644 --- a/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-american +++ b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-american @@ -1 +1 @@ -&%%(and (diary-anniversary 8 15 2004)) Maria Himmelfahrt +&%%(diary-anniversary 8 15 2003) Maria Himmelfahrt diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-european b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-european index 3b82ec09fd5..fa652dbb92e 100644 --- a/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-european +++ b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-european @@ -1 +1 @@ -&%%(and (diary-anniversary 15 8 2004)) Maria Himmelfahrt +&%%(diary-anniversary 15 8 2003) Maria Himmelfahrt diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-iso b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-iso index 7fc99478d4e..803dd36de0a 100644 --- a/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-iso +++ b/test/lisp/calendar/icalendar-resources/import-rrule-anniversary.diary-iso @@ -1 +1 @@ -&%%(and (diary-anniversary 2004 8 15)) Maria Himmelfahrt +&%%(diary-anniversary 2003 8 15) Maria Himmelfahrt diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-american b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-american index a54780b9699..bc485d8a6c4 100644 --- a/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-american +++ b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-american @@ -1 +1 @@ -&%%(and (diary-anniversary 9 19 2003)) 09:00-11:30 rrule yearly +&%%(diary-anniversary 9 19 2002) 09:00-11:30 rrule yearly diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-european b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-european index a4bd81d6f2b..42509d42bc8 100644 --- a/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-european +++ b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-european @@ -1 +1 @@ -&%%(and (diary-anniversary 19 9 2003)) 09:00-11:30 rrule yearly +&%%(diary-anniversary 19 9 2002) 09:00-11:30 rrule yearly diff --git a/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-iso b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-iso index 65a7abe0344..72fe6e12cbd 100644 --- a/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-iso +++ b/test/lisp/calendar/icalendar-resources/import-rrule-yearly.diary-iso @@ -1 +1 @@ -&%%(and (diary-anniversary 2003 9 19)) 09:00-11:30 rrule yearly +&%%(diary-anniversary 2002 9 19) 09:00-11:30 rrule yearly diff --git a/test/lisp/calendar/icalendar-tests.el b/test/lisp/calendar/icalendar-tests.el index 7993a1fd806..61d3c11f6df 100644 --- a/test/lisp/calendar/icalendar-tests.el +++ b/test/lisp/calendar/icalendar-tests.el @@ -87,7 +87,7 @@ (let* ((calendar-date-style 'iso) result) (setq result (icalendar--convert-anniversary-to-ical - "" "%%(diary-anniversary 1964 6 30) g")) + "" "%%(diary-anniversary 1963 6 30) g")) (should (consp result)) (should (string= (concat "\nDTSTART;VALUE=DATE:19640630" @@ -353,7 +353,7 @@ END:VTIMEZONE (let ((calendar-date-style 'iso)) ;; numeric iso (should (string= "20080511" - (icalendar--datestring-to-isodate "2008 05 11"))) + (icalendar--datestring-to-isodate "2008 05 11"))) (should (string= "20080531" (icalendar--datestring-to-isodate "2008 05 31"))) (should (string= "20080602" @@ -384,7 +384,19 @@ END:VTIMEZONE (should (string= "20081105" (icalendar--datestring-to-isodate "05 Nov 2008"))) (should (string= "20081105" - (icalendar--datestring-to-isodate "2008 Nov 05"))))) + (icalendar--datestring-to-isodate "2008 Nov 05"))) + + ;; non-numeric with day-shift and year-shift + (setq calendar-date-style nil) ;not necessary for conversion + (should (string= "20210212" + (icalendar--datestring-to-isodate "2021 Feb 11" 1))) + (should (string= "20210131" + (icalendar--datestring-to-isodate "2021 Feb 11" -11))) + (should (string= "20200211" + (icalendar--datestring-to-isodate "2021 Feb 11" nil -1))) + (should (string= "21010211" + (icalendar--datestring-to-isodate "2021 Feb 11" nil 80))) + )) (ert-deftest icalendar--first-weekday-of-year () "Test method for `icalendar-first-weekday-of-year'." @@ -569,10 +581,10 @@ END:VEVENT ;; testcase: dtstart is mandatory (should (null (icalendar--convert-tz-offset - '((TZOFFSETFROM nil "+0100") - (TZOFFSETTO nil "+0200") - (RRULE nil "FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU")) - t))) + '((TZOFFSETFROM nil "+0100") + (TZOFFSETTO nil "+0200") + (RRULE nil "FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU")) + t))) ;; FIXME: rrule and rdate are NOT mandatory! Must fix code ;; before activating these testcases @@ -830,18 +842,18 @@ SUMMARY:yearly no time "Perform export test." ;; anniversaries (icalendar-tests--test-export - "%%(diary-anniversary 1989 10 3) anniversary no time" - "%%(diary-anniversary 3 10 1989) anniversary no time" - "%%(diary-anniversary 10 3 1989) anniversary no time" + "%%(diary-anniversary 1988 10 3) anniversary no time" + "%%(diary-anniversary 3 10 1988) anniversary no time" + "%%(diary-anniversary 10 3 1988) anniversary no time" "DTSTART;VALUE=DATE:19891003 DTEND;VALUE=DATE:19891004 RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=10;BYMONTHDAY=03 SUMMARY:anniversary no time ") (icalendar-tests--test-export - "%%(diary-anniversary 1989 10 3) 19:00-20:00 anniversary with time" - "%%(diary-anniversary 3 10 1989) 19:00-20:00 anniversary with time" - "%%(diary-anniversary 10 3 1989) 19:00-20:00 anniversary with time" + "%%(diary-anniversary 1988 10 3) 19:00-20:00 anniversary with time" + "%%(diary-anniversary 3 10 1988) 19:00-20:00 anniversary with time" + "%%(diary-anniversary 10 3 1988) 19:00-20:00 anniversary with time" "DTSTART;VALUE=DATE-TIME:19891003T190000 DTEND;VALUE=DATE-TIME:19891004T200000 RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=10;BYMONTHDAY=03 @@ -891,12 +903,12 @@ SUMMARY:no alarm " nil) - ;; 10 minutes in advance, audio - (icalendar-tests--test-export - "2014 Nov 17 19:30 audio alarm" - "17 Nov 2014 19:30 audio alarm" - "Nov 17 2014 19:30 audio alarm" - "DTSTART;VALUE=DATE-TIME:20141117T193000 + ;; 10 minutes in advance, audio + (icalendar-tests--test-export + "2014 Nov 17 19:30 audio alarm" + "17 Nov 2014 19:30 audio alarm" + "Nov 17 2014 19:30 audio alarm" + "DTSTART;VALUE=DATE-TIME:20141117T193000 DTEND;VALUE=DATE-TIME:20141117T203000 SUMMARY:audio alarm BEGIN:VALARM @@ -904,14 +916,14 @@ ACTION:AUDIO TRIGGER:-PT10M END:VALARM " - '(10 ((audio)))) + '(10 ((audio)))) - ;; 20 minutes in advance, display - (icalendar-tests--test-export - "2014 Nov 17 19:30 display alarm" - "17 Nov 2014 19:30 display alarm" - "Nov 17 2014 19:30 display alarm" - "DTSTART;VALUE=DATE-TIME:20141117T193000 + ;; 20 minutes in advance, display + (icalendar-tests--test-export + "2014 Nov 17 19:30 display alarm" + "17 Nov 2014 19:30 display alarm" + "Nov 17 2014 19:30 display alarm" + "DTSTART;VALUE=DATE-TIME:20141117T193000 DTEND;VALUE=DATE-TIME:20141117T203000 SUMMARY:display alarm BEGIN:VALARM @@ -920,14 +932,14 @@ TRIGGER:-PT20M DESCRIPTION:display alarm END:VALARM " - '(20 ((display)))) + '(20 ((display)))) - ;; 66 minutes in advance, email - (icalendar-tests--test-export - "2014 Nov 17 19:30 email alarm" - "17 Nov 2014 19:30 email alarm" - "Nov 17 2014 19:30 email alarm" - "DTSTART;VALUE=DATE-TIME:20141117T193000 + ;; 66 minutes in advance, email + (icalendar-tests--test-export + "2014 Nov 17 19:30 email alarm" + "17 Nov 2014 19:30 email alarm" + "Nov 17 2014 19:30 email alarm" + "DTSTART;VALUE=DATE-TIME:20141117T193000 DTEND;VALUE=DATE-TIME:20141117T203000 SUMMARY:email alarm BEGIN:VALARM @@ -939,14 +951,14 @@ ATTENDEE:MAILTO:att.one@email.com ATTENDEE:MAILTO:att.two@email.com END:VALARM " - '(66 ((email ("att.one@email.com" "att.two@email.com"))))) + '(66 ((email ("att.one@email.com" "att.two@email.com"))))) - ;; 2 minutes in advance, all alarms - (icalendar-tests--test-export - "2014 Nov 17 19:30 all alarms" - "17 Nov 2014 19:30 all alarms" - "Nov 17 2014 19:30 all alarms" - "DTSTART;VALUE=DATE-TIME:20141117T193000 + ;; 2 minutes in advance, all alarms + (icalendar-tests--test-export + "2014 Nov 17 19:30 all alarms" + "17 Nov 2014 19:30 all alarms" + "Nov 17 2014 19:30 all alarms" + "DTSTART;VALUE=DATE-TIME:20141117T193000 DTEND;VALUE=DATE-TIME:20141117T203000 SUMMARY:all alarms BEGIN:VALARM @@ -967,7 +979,7 @@ TRIGGER:-PT2M DESCRIPTION:all alarms END:VALARM " - '(2 ((email ("att.one@email.com" "att.two@email.com")) (audio) (display))))) + '(2 ((email ("att.one@email.com" "att.two@email.com")) (audio) (display))))) ;; ====================================================================== ;; Import tests @@ -1247,7 +1259,7 @@ Argument INPUT icalendar event string." (find-file temp-ics) (goto-char (point-min)) ;;(when (re-search-forward "\nUID:.*\n" nil t) - ;;(replace-match "\n")) + ;;(replace-match "\n")) (let ((cycled (buffer-substring-no-properties (point-min) (point-max)))) (should (string= org-input cycled))))) ;; clean up @@ -1276,8 +1288,8 @@ DESCRIPTION:beschreibung! LOCATION:nowhere ORGANIZER:ulf ") - (icalendar-tests--test-cycle - "UID:4711 + (icalendar-tests--test-cycle + "UID:4711 DTSTART;VALUE=DATE:19190909 DTEND;VALUE=DATE:19190910 RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=09;BYMONTHDAY=09 @@ -1377,7 +1389,7 @@ SUMMARY:ff") " >>> anniversaries: -%%(diary-anniversary 3 28 1991) aa birthday (%d years old)" +%%(diary-anniversary 3 28 1990) aa birthday (%d years old)" "DTSTART;VALUE=DATE:19910328 DTEND;VALUE=DATE:19910329 RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=03;BYMONTHDAY=28 @@ -1387,7 +1399,7 @@ SUMMARY:aa birthday (%d years old) (icalendar-tests--test-export nil nil - "%%(diary-anniversary 5 17 1957) bb birthday (%d years old)" + "%%(diary-anniversary 5 17 1956) bb birthday (%d years old)" "DTSTART;VALUE=DATE:19570517 DTEND;VALUE=DATE:19570518 RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=05;BYMONTHDAY=17 @@ -1396,7 +1408,7 @@ SUMMARY:bb birthday (%d years old)") (icalendar-tests--test-export nil nil - "%%(diary-anniversary 6 8 1997) cc birthday (%d years old)" + "%%(diary-anniversary 6 8 1996) cc birthday (%d years old)" "DTSTART;VALUE=DATE:19970608 DTEND;VALUE=DATE:19970609 RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=06;BYMONTHDAY=08 @@ -1405,7 +1417,7 @@ SUMMARY:cc birthday (%d years old)") (icalendar-tests--test-export nil nil - "%%(diary-anniversary 7 22 1983) dd (%d years ago...!)" + "%%(diary-anniversary 7 22 1982) dd (%d years ago...!)" "DTSTART;VALUE=DATE:19830722 DTEND;VALUE=DATE:19830723 RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=07;BYMONTHDAY=22 @@ -1414,7 +1426,7 @@ SUMMARY:dd (%d years ago...!)") (icalendar-tests--test-export nil nil - "%%(diary-anniversary 8 1 1988) ee birthday (%d years old)" + "%%(diary-anniversary 8 1 1987) ee birthday (%d years old)" "DTSTART;VALUE=DATE:19880801 DTEND;VALUE=DATE:19880802 RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=08;BYMONTHDAY=01 @@ -1423,7 +1435,7 @@ SUMMARY:ee birthday (%d years old)") (icalendar-tests--test-export nil nil - "%%(diary-anniversary 9 21 1957) ff birthday (%d years old)" + "%%(diary-anniversary 9 21 1956) ff birthday (%d years old)" "DTSTART;VALUE=DATE:19570921 DTEND;VALUE=DATE:19570922 RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=09;BYMONTHDAY=21