mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-06-14 12:31:25 +00:00
Rename `icalendar-recur' type and related functions
More context in Bug#80786 and: https://lists.gnu.org/archive/html/emacs-orgmode/2026-03/msg00286.html `icalendar-recur' as a type name for RRULE values was confusing and made the accessors for this type difficult to discover, because `icalendar-recur-' is also used as a prefix in icalendar-recur.el. This change renames the `icalendar-recur' type to `icalendar-rrule-value' and renames the accessor functions for these values appropriately. * lisp/calendar/icalendar-parser.el: Rename symbols as follows: (icalendar-recur): `icalendar-rrule-value' (icalendar-read-recur-rule-part): `icalendar-read-rrule-part' (icalendar-print-recur-rule-part): `icalendar-print-rrule-part' (icalendar-recur-rule-part): `icalendar-rrule-part' (icalendar-read-recur): `icalendar-read-rrule-value' (icalendar-print-recur): `icalendar-print-rrule-value' (icalendar--recur-value-types): `icalendar--rrule-value-types' (icalendar-recur-value-p): `icalendar-rrule-value-p' (icalendar-recur-freq): `icalendar-rrule-freq' (icalendar-recur-interval-size): `icalendar-rrule-interval-size' (icalendar-recur-until): `icalendar-rrule-until' (icalendar-recur-count): `icalendar-rrule-count' (icalendar-recur-weekstart): `icalendar-rrule-weekstart' (icalendar-recur-by*): `icalendar-rrule-by*'. (icalendar-rrule): (icalendar-index-insert): (icalendar-index-get): Update references. * lisp/calendar/icalendar-recur.el (icalendar-recur-find-interval): (icalendar-recur-nth-interval): (icalendar-recur-next-interval): (icalendar-recur-previous-interval): (icalendar-recur-refine-from-clauses): (icalendar-recur-recurrences-in-interval): (icalendar-recur-recurrences-in-window): (icalendar-recur-recurrences-to-count): (icalendar-recur-tz-observance-on): Update references. * lisp/calendar/diary-icalendar.el: Update references. * lisp/calendar/icalendar-shortdoc.el (icalendar): Update shortdoc examples. * lisp/gnus/gnus-icalendar.el: Update references. * test/lisp/calendar/diary-icalendar-tests.el: * test/lisp/calendar/icalendar-parser-tests.el: * test/lisp/calendar/icalendar-recur-tests.el: Update references in tests.
This commit is contained in:
parent
3d2bb233f2
commit
70b79b3ed8
8 changed files with 176 additions and 171 deletions
|
|
@ -2690,12 +2690,12 @@ recurrence rule values in these nodes are adjusted NDAYS forward."
|
|||
:duration (ical:period-dur-value value)))
|
||||
(t (ical:date/time-add value :day ndays)))))))
|
||||
(ical:rrule
|
||||
(let ((mdays (ical:recur-by* 'BYMONTHDAY value))
|
||||
(ydays (ical:recur-by* 'BYYEARDAY value))
|
||||
(dows (ical:recur-by* 'BYDAY value))
|
||||
(let ((mdays (ical:rrule-by* 'BYMONTHDAY value))
|
||||
(ydays (ical:rrule-by* 'BYYEARDAY value))
|
||||
(dows (ical:rrule-by* 'BYDAY value))
|
||||
(bad-clause
|
||||
(cond ((ical:recur-by* 'BYSETPOS value) 'BYSETPOS)
|
||||
((ical:recur-by* 'BYWEEKNO value) 'BYWEEKNO))))
|
||||
(cond ((ical:rrule-by* 'BYSETPOS value) 'BYSETPOS)
|
||||
((ical:rrule-by* 'BYWEEKNO value) 'BYWEEKNO))))
|
||||
;; We can't reliably subtract days in the following cases, so bail:
|
||||
(when (< 28 ndays)
|
||||
(di:signal-export-error
|
||||
|
|
@ -2970,12 +2970,12 @@ nil, if MONTHS, DAYS and YEARS are all integers)."
|
|||
rdates (seq-remove (apply-partially #'equal dtstart) rdates))))
|
||||
|
||||
;; Return the pair of nodes (DTSTART RRULE) or (DTSTART RDATE):
|
||||
(let* ((recur-value
|
||||
(let* ((rrule-value
|
||||
(delq nil
|
||||
`((FREQ ,freq)
|
||||
,(when bymonth (list 'BYMONTH bymonth))
|
||||
,(when bymonthday (list 'BYMONTHDAY bymonthday)))))
|
||||
(rrule-node (when freq (ical:make-property ical:rrule recur-value)))
|
||||
(rrule-node (when freq (ical:make-property ical:rrule rrule-value)))
|
||||
(rdate-node (when rdates
|
||||
(ical:make-property ical:rdate rdates
|
||||
(ical:valuetypeparam rdate-type))))
|
||||
|
|
@ -3548,7 +3548,7 @@ values (of the same type as START)."
|
|||
(interval (icr:find-interval date start rule)))
|
||||
(cl-typecase start
|
||||
(ical:date
|
||||
(if (ical:recur-count rule)
|
||||
(if (ical:rrule-count rule)
|
||||
(when (member date (icr:recurrences-to-count vevent))
|
||||
entry)
|
||||
(when (member date (icr:recurrences-in-interval interval vevent))
|
||||
|
|
@ -3581,7 +3581,7 @@ values (of the same type as START)."
|
|||
(ical:date/time-add-duration start duration))
|
||||
(di:format-time-as-local start)))
|
||||
(date-entry (concat entry-time " " entry)))
|
||||
(when (memq (ical:recur-freq date-rule) '(HOURLY MINUTELY SECONDLY))
|
||||
(when (memq (ical:rrule-freq date-rule) '(HOURLY MINUTELY SECONDLY))
|
||||
(setf (alist-get 'FREQ date-rule) 'DAILY)
|
||||
(setf (alist-get 'INTERVAL date-rule) 1)
|
||||
(setf (alist-get 'BYHOUR date-rule nil t) nil)
|
||||
|
|
|
|||
|
|
@ -1352,9 +1352,9 @@ See `icalendar-read-weekdaynum' for the format of VAL."
|
|||
;; number alone just stands for a day:
|
||||
(car (rassq val ical:weekday-numbers))))
|
||||
|
||||
(defun ical:read-recur-rule-part (s)
|
||||
"Read an `icalendar-recur-rule-part' from string S.
|
||||
S should have been matched against `icalendar-recur-rule-part'.
|
||||
(defun ical:read-rrule-part (s)
|
||||
"Read an `icalendar-rrule-part' from string S.
|
||||
S should have been matched against `icalendar-rrule-part'.
|
||||
The return value is a list (KEYWORD VALUE), where VALUE may
|
||||
itself be a list, depending on the values allowed by KEYWORD."
|
||||
;; TODO: this smells like a design flaw. Silence the byte compiler for now.
|
||||
|
|
@ -1376,7 +1376,7 @@ itself be a list, depending on the values allowed by KEYWORD."
|
|||
(rx ical:weekdaynum) ","))
|
||||
(WKST (cdr (assoc values ical:weekday-numbers)))))))
|
||||
|
||||
(defun ical:print-recur-rule-part (part)
|
||||
(defun ical:print-rrule-part (part)
|
||||
"Serialize recur rule part PART to a string."
|
||||
(let ((keyword (car part))
|
||||
(values (cadr part))
|
||||
|
|
@ -1398,7 +1398,7 @@ itself be a list, depending on the values allowed by KEYWORD."
|
|||
|
||||
(concat (symbol-name keyword) "=" values-str)))
|
||||
|
||||
(rx-define ical:recur-rule-part
|
||||
(rx-define ical:rrule-part
|
||||
;; Group 11: keyword
|
||||
;; Group 12: value(s)
|
||||
(or (seq (group-n 11 "FREQ") "=" (group-n 12 ical:freq))
|
||||
|
|
@ -1423,14 +1423,12 @@ itself be a list, depending on the values allowed by KEYWORD."
|
|||
(ical:comma-list ical:yeardaynum)))
|
||||
(seq (group-n 11 "WKST") "=" (group-n 12 ical:weekday))))
|
||||
|
||||
(defun ical:read-recur (s)
|
||||
(defun ical:read-rrule-value (s)
|
||||
"Read a recurrence rule value from string S.
|
||||
S should be a match against rx `icalendar-recur'."
|
||||
;; TODO: let's switch to keywords and a plist, so we can more easily
|
||||
;; write these clauses also in diary sexp entries without so many parens
|
||||
(ical:read-list-with #'ical:read-recur-rule-part s (rx ical:recur-rule-part) ";"))
|
||||
(ical:read-list-with #'ical:read-rrule-part s (rx ical:rrule-part) ";"))
|
||||
|
||||
(defun ical:print-recur (val)
|
||||
(defun ical:print-rrule-value (val)
|
||||
"Serialize a recurrence rule value VAL to a string."
|
||||
;; RFC5545 sec. 3.3.10: "to ensure backward compatibility with
|
||||
;; applications that pre-date this revision of iCalendar the
|
||||
|
|
@ -1438,15 +1436,15 @@ S should be a match against rx `icalendar-recur'."
|
|||
;; RECUR value."
|
||||
(string-join
|
||||
(cons
|
||||
(ical:print-recur-rule-part (assq 'FREQ val))
|
||||
(mapcar #'ical:print-recur-rule-part
|
||||
(ical:print-rrule-part (assq 'FREQ val))
|
||||
(mapcar #'ical:print-rrule-part
|
||||
(seq-filter (lambda (part) (not (eq 'FREQ (car part))))
|
||||
val)))
|
||||
";"))
|
||||
|
||||
(defconst ical:-recur-value-types
|
||||
(defconst ical:-rrule-value-types
|
||||
;; `list-of' is not a cl-type specifier, just a symbol here; it is
|
||||
;; handled specially when checking types in `ical:recur-value-p':
|
||||
;; handled specially when checking types in `ical:rrule-value-p':
|
||||
'(FREQ (member YEARLY MONTHLY WEEKLY DAILY HOURLY MINUTELY SECONDLY)
|
||||
UNTIL (or ical:date-time ical:date)
|
||||
COUNT (integer 1 *)
|
||||
|
|
@ -1470,7 +1468,7 @@ DAYNO must be in [0..6] and OFFSET in [-53..53], excluding 0."
|
|||
(cl-typep (car val) '(integer 0 6))
|
||||
(cl-typep (cdr val) '(or (integer -53 -1) (integer 1 53)))))
|
||||
|
||||
(defun ical:recur-value-p (vals)
|
||||
(defun ical:rrule-value-p (vals)
|
||||
"Return non-nil if VALS is an iCalendar recurrence rule value."
|
||||
(and (listp vals)
|
||||
;; FREQ is always required:
|
||||
|
|
@ -1487,11 +1485,11 @@ DAYNO must be in [0..6] and OFFSET in [-53..53], excluding 0."
|
|||
(assq 'BYHOUR vals)
|
||||
(assq 'BYMINUTE vals)
|
||||
(assq 'BYSECOND vals))
|
||||
(let ((freq (ical:recur-freq vals))
|
||||
(byday (ical:recur-by* 'BYDAY vals))
|
||||
(byweekno (ical:recur-by* 'BYWEEKNO vals))
|
||||
(bymonthday (ical:recur-by* 'BYMONTHDAY vals))
|
||||
(byyearday (ical:recur-by* 'BYYEARDAY vals)))
|
||||
(let ((freq (ical:rrule-freq vals))
|
||||
(byday (ical:rrule-by* 'BYDAY vals))
|
||||
(byweekno (ical:rrule-by* 'BYWEEKNO vals))
|
||||
(bymonthday (ical:rrule-by* 'BYMONTHDAY vals))
|
||||
(byyearday (ical:rrule-by* 'BYYEARDAY vals)))
|
||||
(and
|
||||
;; "The BYDAY rule part MUST NOT be specified with a numeric
|
||||
;; value when the FREQ rule part is not set to MONTHLY or
|
||||
|
|
@ -1518,7 +1516,7 @@ DAYNO must be in [0..6] and OFFSET in [-53..53], excluding 0."
|
|||
(when (consp kv)
|
||||
(let* ((keyword (car kv))
|
||||
(val (cadr kv))
|
||||
(type (plist-get ical:-recur-value-types keyword)))
|
||||
(type (plist-get ical:-rrule-value-types keyword)))
|
||||
(and keyword val type
|
||||
(if (and (consp type)
|
||||
(eq (car type) 'list-of))
|
||||
|
|
@ -1526,7 +1524,14 @@ DAYNO must be in [0..6] and OFFSET in [-53..53], excluding 0."
|
|||
(cl-typep val type))))))
|
||||
vals)))
|
||||
|
||||
(ical:define-type ical:recur "RECUR"
|
||||
(ical:define-type ical:rrule-value
|
||||
;; Renamed from "ical:recur", which turns out to
|
||||
;; produce confusing names downstream. Thus I've
|
||||
;; deviated from the standard here, and call
|
||||
;; `ical:rrule-value' what the standard calls a RECUR
|
||||
;; value. (`ical:rrule' is not available because that
|
||||
;; names the *property* containing such a value.)
|
||||
"RECUR"
|
||||
"Type for Recurrence Rule values.
|
||||
|
||||
When printed, a recurrence rule value looks like
|
||||
|
|
@ -1587,39 +1592,39 @@ Some examples:
|
|||
Notice that singleton values are still wrapped in a list when the
|
||||
KEY accepts a list of values, but not when the KEY always has a
|
||||
single (e.g. integer) value."
|
||||
'(satisfies ical:recur-value-p)
|
||||
(ical:semicolon-list ical:recur-rule-part)
|
||||
:reader ical:read-recur
|
||||
:printer ical:print-recur
|
||||
'(satisfies ical:rrule-value-p)
|
||||
(ical:semicolon-list ical:rrule-part)
|
||||
:reader ical:read-rrule-value
|
||||
:printer ical:print-rrule-value
|
||||
:link "https://www.rfc-editor.org/rfc/rfc5545#section-3.3.10")
|
||||
|
||||
(defun ical:recur-freq (recur-value)
|
||||
"Return the frequency in RECUR-VALUE."
|
||||
(car (alist-get 'FREQ recur-value)))
|
||||
(defun ical:rrule-freq (rrule)
|
||||
"Return the frequency in RRULE."
|
||||
(car (alist-get 'FREQ rrule)))
|
||||
|
||||
(defun ical:recur-interval-size (recur-value)
|
||||
"Return the interval size in RECUR-VALUE, or the default of 1."
|
||||
(or (car (alist-get 'INTERVAL recur-value)) 1))
|
||||
(defun ical:rrule-interval-size (rrule)
|
||||
"Return the interval size in RRULE, or the default of 1."
|
||||
(or (car (alist-get 'INTERVAL rrule)) 1))
|
||||
|
||||
(defun ical:recur-until (recur-value)
|
||||
"Return the UNTIL date(-time) in RECUR-VALUE."
|
||||
(car (alist-get 'UNTIL recur-value)))
|
||||
(defun ical:rrule-until (rrule)
|
||||
"Return the UNTIL date(-time) in RRULE."
|
||||
(car (alist-get 'UNTIL rrule)))
|
||||
|
||||
(defun ical:recur-count (recur-value)
|
||||
"Return the COUNT in RECUR-VALUE."
|
||||
(car (alist-get 'COUNT recur-value)))
|
||||
(defun ical:rrule-count (rrule)
|
||||
"Return the COUNT in RRULE."
|
||||
(car (alist-get 'COUNT rrule)))
|
||||
|
||||
(defun ical:recur-weekstart (recur-value)
|
||||
"Return the weekday which starts the work week in RECUR-VALUE.
|
||||
If no starting weekday is specified in RECUR-VALUE, returns the default,
|
||||
(defun ical:rrule-weekstart (rrule)
|
||||
"Return the weekday which starts the work week in RRULE.
|
||||
If no starting weekday is specified in RRULE, returns the default,
|
||||
1 (= Monday)."
|
||||
(or (car (alist-get 'WKST recur-value)) 1))
|
||||
(or (car (alist-get 'WKST rrule)) 1))
|
||||
|
||||
(defun ical:recur-by* (byunit recur-value)
|
||||
"Return the values in the BYUNIT clause in RECUR-VALUE.
|
||||
(defun ical:rrule-by* (byunit rrule)
|
||||
"Return the values in the BYUNIT clause in RRULE.
|
||||
BYUNIT should be a symbol: \\='BYMONTH, \\='BYDAY, etc.
|
||||
See `icalendar-recur' for all the possible BYUNIT values."
|
||||
(car (alist-get byunit recur-value)))
|
||||
See `icalendar-rrule-value' for all the possible BYUNIT values."
|
||||
(car (alist-get byunit rrule)))
|
||||
|
||||
;;;; 3.3.11 Text
|
||||
(rx-define ical:escaped-char
|
||||
|
|
@ -3272,7 +3277,7 @@ and times on which an `icalendar-vevent', `icalendar-todo',
|
|||
`icalendar-daylight' component recurs. Together with the
|
||||
`icalendar-dtstart', `icalendar-rdate', and `icalendar-exdate'
|
||||
properties, it defines the recurrence set of the component."
|
||||
ical:recur
|
||||
ical:rrule-value
|
||||
;; TODO: faces for subexpressions?
|
||||
:child-spec (:zero-or-more (ical:otherparam))
|
||||
:link "https://www.rfc-editor.org/rfc/rfc5545#section-3.8.5.3")
|
||||
|
|
@ -4567,7 +4572,7 @@ which see."
|
|||
(ical:dtend :first dtend-node :value dtend)
|
||||
(ical:due :value due)
|
||||
(ical:duration :value duration)
|
||||
(ical:rrule :value recur-value)
|
||||
(ical:rrule :value rrule)
|
||||
(ical:rdate :all rdate-nodes)
|
||||
(ical:exdate :all exdate-nodes)
|
||||
(ical:uid :value uid))
|
||||
|
|
@ -4592,7 +4597,7 @@ which see."
|
|||
;; If the component has an RRULE that specifies a fixed number
|
||||
;; of recurrences, compute them now and index them for each date
|
||||
;; in each recurrence:
|
||||
((and recur-value (ical:recur-count recur-value))
|
||||
((and rrule (ical:rrule-count rrule))
|
||||
(let* ((tz (gethash (ical:with-param-of dtstart-node 'ical:tzidparam)
|
||||
tzid-index))
|
||||
(recs (cons dtstart (icr:recurrences-to-count component tz))))
|
||||
|
|
@ -4605,7 +4610,7 @@ which see."
|
|||
(list (ical:date/time-to-date
|
||||
(ical:date/time-to-local rec))))))))))
|
||||
;; Same with RDATEs when there's no RRULE:
|
||||
((and rdates (not recur-value))
|
||||
((and rdates (not rrule))
|
||||
(dolist (rec (cons dtstart rdates))
|
||||
(unless (or (cl-typep rec 'ical:period) (member rec exdates))
|
||||
(let ((end-time
|
||||
|
|
@ -4624,7 +4629,7 @@ which see."
|
|||
(setq dates (append dates (ical:dates-until start end t)))))))
|
||||
;; A non-recurring event also gets an index entry for each date
|
||||
;; until its end time:
|
||||
((not recur-value)
|
||||
((not rrule)
|
||||
(let ((end-time
|
||||
(or dtend due
|
||||
(when duration
|
||||
|
|
@ -4703,13 +4708,13 @@ Only one keyword argument can be queried at a time."
|
|||
(dolist (component recurring)
|
||||
(ical:with-component component
|
||||
((ical:dtstart :first dtstart-node :value dtstart)
|
||||
(ical:rrule :value recur-value)
|
||||
(ical:rrule :value rrule)
|
||||
(ical:rdate :all rdate-nodes)
|
||||
(ical:duration :value duration))
|
||||
(unless (ical:date/time<= date dtstart)
|
||||
(let* ((tz (ical:with-param-of dtstart-node 'ical:tzidparam nil
|
||||
(gethash value (plist-get index :bytzid))))
|
||||
(int (icr:find-interval date dtstart recur-value tz))
|
||||
(int (icr:find-interval date dtstart rrule tz))
|
||||
(recs (icr:recurrences-in-interval int component tz)))
|
||||
(catch 'found
|
||||
(dolist (rec recs)
|
||||
|
|
|
|||
|
|
@ -451,29 +451,29 @@ See `icalendar-recur-find-interval' for arguments' meanings."
|
|||
;; Return the bounds:
|
||||
(icr:make-interval low high next-low)))
|
||||
|
||||
(defun icr:find-interval (target dtstart recur-value &optional vtimezone)
|
||||
(defun icr:find-interval (target dtstart rrule &optional vtimezone)
|
||||
"Return the recurrence interval around TARGET.
|
||||
|
||||
TARGET and DTSTART should be `icalendar-date' or `icalendar-date-time'
|
||||
values. RECUR-VALUE should be an `icalendar-recur'.
|
||||
values. RRULE should be an `icalendar-recur'.
|
||||
|
||||
The returned value is an interval [LOW HIGH NEXT-LOW] which
|
||||
represents the lower and upper bounds of a recurrence interval around
|
||||
TARGET. For some N, LOW is equal to START + N*INTERVALSIZE units, HIGH
|
||||
is equal to START + (N+1)*INTERVALSIZE units, and LOW <= TARGET < HIGH.
|
||||
START here is a time derived from DTSTART depending on RECUR-VALUE's
|
||||
START here is a time derived from DTSTART depending on RRULE's
|
||||
FREQ part: the first day of the year for a \\='YEARLY rule, first day
|
||||
of the month for a \\='MONTHLY rule, etc.
|
||||
|
||||
RECUR-VALUE's interval determines INTERVALSIZE, and its frequency
|
||||
RRULE's interval determines INTERVALSIZE, and its frequency
|
||||
determines the units: a month for \\='MONTHLY, etc.
|
||||
|
||||
If VTIMEZONE is provided, it is used to set time zone information in the
|
||||
returned interval bounds. Otherwise, the bounds contain no time zone
|
||||
information and represent floating local times."
|
||||
(let ((freq (ical:recur-freq recur-value))
|
||||
(intsize (ical:recur-interval-size recur-value))
|
||||
(weekstart (ical:recur-weekstart recur-value)))
|
||||
(let ((freq (ical:rrule-freq rrule))
|
||||
(intsize (ical:rrule-interval-size rrule))
|
||||
(weekstart (ical:rrule-weekstart rrule)))
|
||||
(cl-case freq
|
||||
(SECONDLY (icr:find-secondly-interval target dtstart intsize vtimezone))
|
||||
(MINUTELY (icr:find-minutely-interval target dtstart intsize vtimezone))
|
||||
|
|
@ -484,22 +484,22 @@ information and represent floating local times."
|
|||
(MONTHLY (icr:find-monthly-interval target dtstart intsize vtimezone))
|
||||
(YEARLY (icr:find-yearly-interval target dtstart intsize vtimezone)))))
|
||||
|
||||
(defun icr:nth-interval (n dtstart recur-value &optional vtimezone)
|
||||
(defun icr:nth-interval (n dtstart rrule &optional vtimezone)
|
||||
"Return the Nth recurrence interval after DTSTART.
|
||||
|
||||
The returned value is an interval [LOW HIGH NEXT-LOW] which is the Nth
|
||||
recurrence interval after DTSTART. LOW is equal to START +
|
||||
N*INTERVALSIZE units, HIGH is equal to START + (N+1)*INTERVALSIZE units,
|
||||
and LOW <= TARGET < HIGH. START here is a time derived from DTSTART
|
||||
depending on RECUR-VALUE's FREQ part: the first day of the year for a
|
||||
depending on RRULE's FREQ part: the first day of the year for a
|
||||
\\='YEARLY rule, first day of the month for a \\='MONTHLY rule, etc.
|
||||
|
||||
RECUR-VALUE's interval determines INTERVALSIZE, and its frequency
|
||||
RRULE's interval determines INTERVALSIZE, and its frequency
|
||||
determines the units: a month for \\='MONTHLY, etc.
|
||||
|
||||
N should be a non-negative integer. Interval 0 is the interval
|
||||
containing DTSTART. DTSTART should be an `icalendar-date' or
|
||||
`icalendar-date-time' value. RECUR-VALUE should be an
|
||||
`icalendar-date-time' value. RRULE should be an
|
||||
`icalendar-recur'.
|
||||
|
||||
If VTIMEZONE is provided, it is used to set time zone information in the
|
||||
|
|
@ -509,8 +509,8 @@ information and represent floating local times."
|
|||
(let* ((start-dt (if (cl-typep dtstart 'ical:date)
|
||||
(ical:date-to-date-time dtstart :tz vtimezone)
|
||||
dtstart))
|
||||
(freq (ical:recur-freq recur-value))
|
||||
(intervalsize (ical:recur-interval-size recur-value))
|
||||
(freq (ical:rrule-freq rrule))
|
||||
(intervalsize (ical:rrule-interval-size rrule))
|
||||
(unit (cl-case freq
|
||||
(YEARLY :year)
|
||||
(MONTHLY :month)
|
||||
|
|
@ -520,16 +520,16 @@ information and represent floating local times."
|
|||
(MINUTELY :minute)
|
||||
(SECONDLY :second)))
|
||||
(target (ical:date/time-add start-dt unit (* n intervalsize) vtimezone)))
|
||||
(icr:find-interval target dtstart recur-value vtimezone)))
|
||||
(icr:find-interval target dtstart rrule vtimezone)))
|
||||
|
||||
(defun icr:next-interval (interval recur-value &optional vtimezone)
|
||||
(defun icr:next-interval (interval rrule &optional vtimezone)
|
||||
"Return the next recurrence interval after INTERVAL.
|
||||
|
||||
Given a recurrence interval [LOW HIGH NEXT], returns the next interval
|
||||
[NEXT HIGHER HIGHER-NEXT], where HIGHER and HIGHER-NEXT are determined
|
||||
by the frequency and interval sizes of RECUR-VALUE."
|
||||
by the frequency and interval sizes of RRULE."
|
||||
(let* ((new-low (icr:interval-next interval))
|
||||
(freq (ical:recur-freq recur-value))
|
||||
(freq (ical:rrule-freq rrule))
|
||||
(unit (cl-case freq
|
||||
(YEARLY :year)
|
||||
(MONTHLY :month)
|
||||
|
|
@ -538,7 +538,7 @@ by the frequency and interval sizes of RECUR-VALUE."
|
|||
(HOURLY :hour)
|
||||
(MINUTELY :minute)
|
||||
(SECONDLY :second)))
|
||||
(intervalsize (ical:recur-interval-size recur-value))
|
||||
(intervalsize (ical:rrule-interval-size rrule))
|
||||
(new-high (ical:date/time-add new-low unit 1 vtimezone))
|
||||
(new-next
|
||||
(when (< 1 intervalsize)
|
||||
|
|
@ -552,17 +552,17 @@ by the frequency and interval sizes of RECUR-VALUE."
|
|||
|
||||
(icr:make-interval new-low new-high new-next)))
|
||||
|
||||
(defun icr:previous-interval (interval recur-value dtstart &optional vtimezone)
|
||||
(defun icr:previous-interval (interval rrule dtstart &optional vtimezone)
|
||||
"Given a recurrence INTERVAL, return the previous interval.
|
||||
|
||||
For an interval [LOW HIGH NEXT-LOW], the previous interval is
|
||||
[PREV-LOW PREV-HIGH LOW], where PREV-LOW and PREV-HIGH are determined by
|
||||
the frequency and interval sizes of RECUR-VALUE (see
|
||||
the frequency and interval sizes of RRULE (see
|
||||
`icalendar-recur-find-interval'). If the resulting period of time
|
||||
between PREV-LOW and PREV-HIGH occurs entirely before DTSTART, then the
|
||||
interval does not exist; in this case nil is returned."
|
||||
(let* ((upper (icr:interval-low interval))
|
||||
(freq (ical:recur-freq recur-value))
|
||||
(freq (ical:rrule-freq rrule))
|
||||
(unit (cl-case freq
|
||||
(YEARLY :year)
|
||||
(MONTHLY :month)
|
||||
|
|
@ -571,7 +571,7 @@ interval does not exist; in this case nil is returned."
|
|||
(HOURLY :hour)
|
||||
(MINUTELY :minute)
|
||||
(SECONDLY :second)))
|
||||
(intervalsize (ical:recur-interval-size recur-value))
|
||||
(intervalsize (ical:rrule-interval-size rrule))
|
||||
(new-low (ical:date/time-add upper unit (* -1 intervalsize) vtimezone))
|
||||
(new-high
|
||||
(if (< 1 intervalsize)
|
||||
|
|
@ -1032,12 +1032,12 @@ The returned value is RECURRENCES filtered by index."
|
|||
(pop dts))
|
||||
(nreverse r)))
|
||||
|
||||
(defun icr:refine-from-clauses (interval recur-value dtstart
|
||||
(defun icr:refine-from-clauses (interval rrule dtstart
|
||||
&optional vtimezone)
|
||||
"Resolve INTERVAL into subintervals based on the clauses in RECUR-VALUE.
|
||||
"Resolve INTERVAL into subintervals based on the clauses in RRULE.
|
||||
|
||||
The resulting list of subintervals represents all times in INTERVAL
|
||||
which match the BY* clauses of RECUR-VALUE except BYSETPOS, as well as
|
||||
which match the BY* clauses of RRULE except BYSETPOS, as well as
|
||||
the constraints implicit in DTSTART. (For example, if there is no
|
||||
BYMINUTE clause, subintervals will have the same minute value as
|
||||
DTSTART.)
|
||||
|
|
@ -1047,14 +1047,14 @@ components and TZID should be the `icalendar-tzid' property value of one
|
|||
of those timezones. In this case, TZID states the time zone of DTSTART,
|
||||
and the offsets effective in that time zone on the dates and times of
|
||||
recurrences will be local to that time zone."
|
||||
(let ((freq (ical:recur-freq recur-value))
|
||||
(weekstart (ical:recur-weekstart recur-value))
|
||||
(let ((freq (ical:rrule-freq rrule))
|
||||
(weekstart (ical:rrule-weekstart rrule))
|
||||
(subintervals (list interval)))
|
||||
|
||||
(dolist (byunit (list 'BYMONTH 'BYWEEKNO
|
||||
'BYYEARDAY 'BYMONTHDAY 'BYDAY
|
||||
'BYHOUR 'BYMINUTE 'BYSECOND))
|
||||
(let ((values (ical:recur-by* byunit recur-value))
|
||||
(let ((values (ical:rrule-by* byunit rrule))
|
||||
(in-month nil))
|
||||
;; When there is no explicit BY* clause, use the value implicit
|
||||
;; in DTSTART. (These conditions are adapted from RFC8984:
|
||||
|
|
@ -1086,26 +1086,26 @@ recurrences will be local to that time zone."
|
|||
(setq values (list (ical:date/time-weekday dtstart))))
|
||||
(when (and (eq byunit 'BYMONTHDAY)
|
||||
(eq freq 'MONTHLY)
|
||||
(not (ical:recur-by* 'BYDAY recur-value))
|
||||
(not (ical:rrule-by* 'BYDAY rrule))
|
||||
(not values))
|
||||
(setq values (list (ical:date/time-monthday dtstart))))
|
||||
(when (and (eq freq 'YEARLY)
|
||||
(not (ical:recur-by* 'BYYEARDAY recur-value)))
|
||||
(not (ical:rrule-by* 'BYYEARDAY rrule)))
|
||||
(when (and (eq byunit 'BYMONTH)
|
||||
(not values)
|
||||
(not (ical:recur-by* 'BYWEEKNO recur-value))
|
||||
(or (ical:recur-by* 'BYMONTHDAY recur-value)
|
||||
(not (ical:recur-by* 'BYDAY recur-value))))
|
||||
(not (ical:rrule-by* 'BYWEEKNO rrule))
|
||||
(or (ical:rrule-by* 'BYMONTHDAY rrule)
|
||||
(not (ical:rrule-by* 'BYDAY rrule))))
|
||||
(setq values (list (ical:date/time-month dtstart))))
|
||||
(when (and (eq byunit 'BYMONTHDAY)
|
||||
(not values)
|
||||
(not (ical:recur-by* 'BYWEEKNO recur-value))
|
||||
(not (ical:recur-by* 'BYDAY recur-value)))
|
||||
(not (ical:rrule-by* 'BYWEEKNO rrule))
|
||||
(not (ical:rrule-by* 'BYDAY rrule)))
|
||||
(setq values (list (ical:date/time-monthday dtstart))))
|
||||
(when (and (eq byunit 'BYDAY)
|
||||
(not values)
|
||||
(ical:recur-by* 'BYWEEKNO recur-value)
|
||||
(not (ical:recur-by* 'BYMONTHDAY recur-value)))
|
||||
(ical:rrule-by* 'BYWEEKNO rrule)
|
||||
(not (ical:rrule-by* 'BYMONTHDAY rrule)))
|
||||
(setq values (list (ical:date/time-weekday dtstart)))))
|
||||
|
||||
;; Handle offsets in a BYDAY clause:
|
||||
|
|
@ -1120,7 +1120,7 @@ recurrences will be local to that time zone."
|
|||
(when (and (eq byunit 'BYDAY)
|
||||
(or (eq freq 'MONTHLY)
|
||||
(and (eq freq 'YEARLY)
|
||||
(ical:recur-by* 'BYMONTH recur-value))))
|
||||
(ical:rrule-by* 'BYMONTH rrule))))
|
||||
(setq in-month t))
|
||||
|
||||
;; On each iteration of the loop, we refine the subintervals
|
||||
|
|
@ -1246,10 +1246,10 @@ retrieved on subsequent calls with the same arguments."
|
|||
(ical:with-component component
|
||||
((ical:dtstart :value dtstart)
|
||||
(ical:tzoffsetfrom :value offset-from)
|
||||
(ical:rrule :value recur-value)
|
||||
(ical:rrule :value rrule)
|
||||
(ical:rdate :all rdate-nodes) ;; TODO: these can also be ical:period values
|
||||
(ical:exdate :all exdate-nodes))
|
||||
(if (not (or recur-value rdate-nodes))
|
||||
(if (not (or rrule rdate-nodes))
|
||||
;; No recurrences to calculate, so just return early:
|
||||
nil
|
||||
;; Otherwise, calculate recurrences in the interval:
|
||||
|
|
@ -1267,19 +1267,19 @@ retrieved on subsequent calls with the same arguments."
|
|||
(t
|
||||
(let* (;; Start by generating all the recurrences matching the
|
||||
;; BY* clauses except for BYSETPOS:
|
||||
(subs (icr:refine-from-clauses interval recur-value dtstart
|
||||
(subs (icr:refine-from-clauses interval rrule dtstart
|
||||
vtimezone))
|
||||
(sub-recs (icr:subintervals-to-recurrences subs dtstart
|
||||
vtimezone))
|
||||
;; Apply any BYSETPOS clause to this set:
|
||||
(keep-indices (ical:recur-by* 'BYSETPOS recur-value))
|
||||
(keep-indices (ical:rrule-by* 'BYSETPOS rrule))
|
||||
(pos-recs
|
||||
(if keep-indices
|
||||
(icr:bysetpos-filter keep-indices sub-recs)
|
||||
sub-recs))
|
||||
;; Remove any recurrences before DTSTART or after UNTIL
|
||||
;; (both of which are inclusive bounds):
|
||||
(until (ical:recur-until recur-value))
|
||||
(until (ical:rrule-until rrule))
|
||||
(until-recs
|
||||
(seq-filter
|
||||
(lambda (rec) (and (ical:date/time<= dtstart rec)
|
||||
|
|
@ -1345,9 +1345,9 @@ UTC offsets local to that time zone."
|
|||
(ical:with-component component
|
||||
((ical:dtstart :value dtstart)
|
||||
(ical:tzoffsetfrom :value offset-from)
|
||||
(ical:rrule :value recur-value)
|
||||
(ical:rrule :value rrule)
|
||||
(ical:rdate :all rdate-nodes))
|
||||
(if (not (or recur-value rdate-nodes))
|
||||
(if (not (or rrule rdate-nodes))
|
||||
;; No recurrences to calculate, so just return early:
|
||||
nil
|
||||
;; Otherwise, calculate the recurrences in the window:
|
||||
|
|
@ -1362,11 +1362,11 @@ UTC offsets local to that time zone."
|
|||
|
||||
(let* (;; don't look for nonexistent intervals:
|
||||
(low-start (if (ical:date/time< lower dtstart) dtstart lower))
|
||||
(until (ical:recur-until recur-value))
|
||||
(until (ical:rrule-until rrule))
|
||||
(high-end (if (and until (ical:date/time< until upper)) until upper))
|
||||
(curr-interval (icr:find-interval low-start dtstart recur-value
|
||||
(curr-interval (icr:find-interval low-start dtstart rrule
|
||||
vtimezone))
|
||||
(high-interval (icr:find-interval high-end dtstart recur-value
|
||||
(high-interval (icr:find-interval high-end dtstart rrule
|
||||
vtimezone))
|
||||
(high-intbound (icr:interval-high high-interval))
|
||||
(recurrences nil))
|
||||
|
|
@ -1376,7 +1376,7 @@ UTC offsets local to that time zone."
|
|||
(nconc
|
||||
(icr:recurrences-in-interval curr-interval component vtimezone)
|
||||
recurrences))
|
||||
(setq curr-interval (icr:next-interval curr-interval recur-value
|
||||
(setq curr-interval (icr:next-interval curr-interval rrule
|
||||
vtimezone)))
|
||||
|
||||
;; exclude any recurrences inside the first and last intervals but
|
||||
|
|
@ -1447,7 +1447,7 @@ UTC offsets local to that time zone."
|
|||
(ical:with-component component
|
||||
((ical:dtstart :value dtstart)
|
||||
(ical:tzoffsetfrom :value offset-from)
|
||||
(ical:rrule :value recur-value)
|
||||
(ical:rrule :value rrule)
|
||||
(ical:rdate :all rdate-nodes))
|
||||
(when (memq (ical:ast-node-type component) '(ical:standard ical:daylight))
|
||||
;; in time zone observances, set the zone field in dtstart
|
||||
|
|
@ -1457,18 +1457,18 @@ UTC offsets local to that time zone."
|
|||
:zone offset-from
|
||||
:dst (not (ical:daylight-component-p
|
||||
component)))))
|
||||
(unless (or recur-value rdate-nodes)
|
||||
(unless (or rrule rdate-nodes)
|
||||
(error "No recurrence data in component: %s" component))
|
||||
(unless (ical:recur-count recur-value)
|
||||
(unless (ical:rrule-count rrule)
|
||||
(error "Recurrence rule has no COUNT clause"))
|
||||
(let ((count (ical:recur-count recur-value))
|
||||
(int (icr:nth-interval 0 dtstart recur-value vtimezone))
|
||||
(let ((count (ical:rrule-count rrule))
|
||||
(int (icr:nth-interval 0 dtstart rrule vtimezone))
|
||||
recs)
|
||||
(while (length< recs count)
|
||||
(setq recs
|
||||
(nconc recs (icr:recurrences-in-interval int component vtimezone
|
||||
(- count (length recs)))))
|
||||
(setq int (icr:next-interval int recur-value vtimezone)))
|
||||
(setq int (icr:next-interval int rrule vtimezone)))
|
||||
recs)))
|
||||
|
||||
|
||||
|
|
@ -1771,7 +1771,7 @@ ignored."
|
|||
(dolist (obs (append stds dls))
|
||||
(ical:with-component obs
|
||||
((ical:dtstart :value start)
|
||||
(ical:rrule :value recur-value)
|
||||
(ical:rrule :value rrule)
|
||||
(ical:rdate :all rdate-nodes)
|
||||
(ical:tzoffsetfrom :value offset-from))
|
||||
;; DTSTART of the observance must be given as local time, and is
|
||||
|
|
@ -1781,7 +1781,7 @@ ignored."
|
|||
(effective-start
|
||||
(ical:date-time-variant start :zone offset-from
|
||||
:dst (not is-daylight)))
|
||||
(until (ical:recur-until recur-value))
|
||||
(until (ical:rrule-until rrule))
|
||||
(bound
|
||||
;; Optimization: compute a rough upper bound for when
|
||||
;; an observance might apply, thus allowing us to skip
|
||||
|
|
@ -1796,8 +1796,8 @@ ignored."
|
|||
(when until
|
||||
(ical:date-time-variant until
|
||||
:year (+ (decoded-time-year until)
|
||||
(ical:recur-interval-size
|
||||
recur-value)))))
|
||||
(ical:rrule-interval-size
|
||||
rrule)))))
|
||||
(observance-might-apply
|
||||
(if given-clock-time
|
||||
(icr:-w/in-locally-p given-clock-time effective-start bound)
|
||||
|
|
@ -1859,11 +1859,11 @@ ignored."
|
|||
;; start of each observance onset), which
|
||||
;; `icr:tz-set-zone' knows to handle specially without
|
||||
;; calling this function.
|
||||
(when recur-value
|
||||
(when rrule
|
||||
(let* ((target (or given-clock-time
|
||||
(decode-time given-abs-time offset-from)))
|
||||
(int (icr:find-interval
|
||||
target effective-start recur-value offset-from))
|
||||
target effective-start rrule offset-from))
|
||||
(<=given
|
||||
(if given-clock-time
|
||||
(lambda (rec)
|
||||
|
|
@ -1883,7 +1883,7 @@ ignored."
|
|||
;; actually be in the previous interval, e.g.
|
||||
;; if `dt' is in January after an annual change to
|
||||
;; Standard Time in November. So check that as well.
|
||||
(setq int (icr:previous-interval int recur-value
|
||||
(setq int (icr:previous-interval int rrule
|
||||
effective-start
|
||||
offset-from))
|
||||
(setq int-recs
|
||||
|
|
|
|||
|
|
@ -252,22 +252,22 @@
|
|||
"(icalendar-recur-recurrences-to-count '(1 1 2026) '(12 31 2026)
|
||||
vevent)"
|
||||
:eg-result-string "((1 10 2026) (2 10 2026) (3 10 2026))")
|
||||
(icalendar-recur-freq
|
||||
(icalendar-rrule-freq
|
||||
:eval
|
||||
(icalendar-recur-freq '((FREQ MONTHLY) (INTERVAL 3) (BYDAY ((5 . -1))))))
|
||||
(icalendar-recur-interval-size
|
||||
:eval (icalendar-recur-interval-size '((FREQ MONTHLY) (BYDAY ((5 . -1)))))
|
||||
:eval (icalendar-recur-interval-size '((FREQ MONTHLY) (INTERVAL 3))))
|
||||
(icalendar-recur-count
|
||||
:eval (icalendar-recur-count '((FREQ MONTHLY) (INTERVAL 2) (COUNT 6))))
|
||||
(icalendar-recur-until
|
||||
:eval (icalendar-recur-until '((FREQ WEEKLY) (UNTIL (12 31 2026)))))
|
||||
(icalendar-recur-by*
|
||||
:eval (icalendar-recur-by* 'BYDAY '((FREQ MONTHLY) (BYDAY ((5 . -1))))))
|
||||
(icalendar-recur-weekstart
|
||||
(icalendar-rrule-freq '((FREQ MONTHLY) (INTERVAL 3) (BYDAY ((5 . -1))))))
|
||||
(icalendar-rrule-interval-size
|
||||
:eval (icalendar-rrule-interval-size '((FREQ MONTHLY) (BYDAY ((5 . -1)))))
|
||||
:eval (icalendar-rrule-interval-size '((FREQ MONTHLY) (INTERVAL 3))))
|
||||
(icalendar-rrule-count
|
||||
:eval (icalendar-rrule-count '((FREQ MONTHLY) (INTERVAL 2) (COUNT 6))))
|
||||
(icalendar-rrule-until
|
||||
:eval (icalendar-rrule-until '((FREQ WEEKLY) (UNTIL (12 31 2026)))))
|
||||
(icalendar-rrule-by*
|
||||
:eval (icalendar-rrule-by* 'BYDAY '((FREQ MONTHLY) (BYDAY ((5 . -1))))))
|
||||
(icalendar-rrule-weekstart
|
||||
:eval
|
||||
(icalendar-recur-weekstart '((FREQ WEEKLY) (UNTIL (12 31 2026)) (WKST 0)))
|
||||
(icalendar-rrule-weekstart '((FREQ WEEKLY) (UNTIL (12 31 2026)) (WKST 0)))
|
||||
:eval
|
||||
(icalendar-recur-weekstart '((FREQ WEEKLY) (UNTIL (12 31 2026))))))
|
||||
(icalendar-rrule-weekstart '((FREQ WEEKLY) (UNTIL (12 31 2026))))))
|
||||
|
||||
(provide 'icalendar-shortdoc)
|
||||
|
|
|
|||
|
|
@ -131,18 +131,18 @@
|
|||
|
||||
(cl-defmethod gnus-icalendar-event:recurring-freq ((event gnus-icalendar-event))
|
||||
"Return recurring frequency of EVENT."
|
||||
(ical:recur-freq (gnus-icalendar-event:recur event)))
|
||||
(ical:rrule-freq (gnus-icalendar-event:recur event)))
|
||||
|
||||
(cl-defmethod gnus-icalendar-event:recurring-interval ((event gnus-icalendar-event))
|
||||
"Return recurring interval of EVENT."
|
||||
(ical:recur-interval-size (gnus-icalendar-event:recur event)))
|
||||
(ical:rrule-interval-size (gnus-icalendar-event:recur event)))
|
||||
|
||||
(cl-defmethod gnus-icalendar-event:recurring-days ((event gnus-icalendar-event))
|
||||
"Return, when available, the week day numbers on which the EVENT recurs."
|
||||
(let ((rrule (gnus-icalendar-event:recur event)))
|
||||
(when rrule
|
||||
(mapcar (lambda (el) (if (consp el) (car el) el))
|
||||
(ical:recur-by* 'BYDAY rrule)))))
|
||||
(ical:rrule-by* 'BYDAY rrule)))))
|
||||
|
||||
(cl-defmethod gnus-icalendar-event:start ((event gnus-icalendar-event))
|
||||
(format-time-string "%Y-%m-%d %H:%M" (gnus-icalendar-event:start-time event)))
|
||||
|
|
|
|||
|
|
@ -817,8 +817,8 @@ SOURCE, if given, should be a symbol; it is used to name the test."
|
|||
(should (equal (ical:date-time-to-date dtstart)
|
||||
(calendar-nth-named-day 1 4 1 di:recurring-start-year)))
|
||||
(should (= 16 (decoded-time-hour dtstart)))
|
||||
(should (eq (ical:recur-freq rrule) 'WEEKLY))
|
||||
(should (equal (ical:recur-by* 'BYDAY rrule) (list 4)))))
|
||||
(should (eq (ical:rrule-freq rrule) 'WEEKLY))
|
||||
(should (equal (ical:rrule-by* 'BYDAY rrule) (list 4)))))
|
||||
|
||||
(dit:parse-test
|
||||
;; Multiline entry, parsed as one event:
|
||||
|
|
@ -961,10 +961,10 @@ SOURCE, if given, should be a symbol; it is used to name the test."
|
|||
:tests
|
||||
(ical:with-component (car parsed)
|
||||
((ical:dtstart :value dtstart)
|
||||
(ical:rrule :value recur-value)
|
||||
(ical:rrule :value rrule)
|
||||
(ical:summary :value summary))
|
||||
(should (equal dtstart '(5 28 1995)))
|
||||
(should (eq (ical:recur-freq recur-value) 'YEARLY))
|
||||
(should (eq (ical:rrule-freq rrule) 'YEARLY))
|
||||
(should (equal summary "H's birthday"))))
|
||||
|
||||
(dit:parse-test
|
||||
|
|
@ -977,11 +977,11 @@ SOURCE, if given, should be a symbol; it is used to name the test."
|
|||
:tests
|
||||
(ical:with-component (car parsed)
|
||||
((ical:dtstart :value dtstart)
|
||||
(ical:rrule :value recur-value)
|
||||
(ical:rrule :value rrule)
|
||||
(ical:summary :value summary))
|
||||
(should (equal dtstart '(6 24 2012)))
|
||||
(should (equal (ical:recur-freq recur-value) 'DAILY))
|
||||
(should (equal (ical:recur-until recur-value) '(7 10 2012)))
|
||||
(should (equal (ical:rrule-freq rrule) 'DAILY))
|
||||
(should (equal (ical:rrule-until rrule) '(7 10 2012)))
|
||||
(should (equal summary "Vacation"))))
|
||||
|
||||
(dit:parse-test
|
||||
|
|
@ -994,11 +994,11 @@ SOURCE, if given, should be a symbol; it is used to name the test."
|
|||
:tests
|
||||
(ical:with-component (car parsed)
|
||||
((ical:dtstart :value dtstart)
|
||||
(ical:rrule :value recur-value)
|
||||
(ical:rrule :value rrule)
|
||||
(ical:summary :value summary))
|
||||
(should (equal dtstart '(3 1 2012)))
|
||||
(should (eq (ical:recur-freq recur-value) 'DAILY))
|
||||
(should (eq (ical:recur-interval-size recur-value) 50))
|
||||
(should (eq (ical:rrule-freq rrule) 'DAILY))
|
||||
(should (eq (ical:rrule-interval-size rrule) 50))
|
||||
(should (equal summary "Renew medication"))))
|
||||
|
||||
(dit:parse-test
|
||||
|
|
@ -1011,13 +1011,13 @@ SOURCE, if given, should be a symbol; it is used to name the test."
|
|||
:tests
|
||||
(ical:with-component (car parsed)
|
||||
((ical:dtstart :value dtstart)
|
||||
(ical:rrule :value recur-value)
|
||||
(ical:rrule :value rrule)
|
||||
(ical:summary :value summary))
|
||||
(should (equal dtstart
|
||||
(calendar-nth-named-day 4 4 11 di:recurring-start-year)))
|
||||
(should (eq (ical:recur-freq recur-value) 'MONTHLY))
|
||||
(should (equal (ical:recur-by* 'BYMONTH recur-value) (list 11)))
|
||||
(should (equal (ical:recur-by* 'BYDAY recur-value) (list '(4 . 4))))
|
||||
(should (eq (ical:rrule-freq rrule) 'MONTHLY))
|
||||
(should (equal (ical:rrule-by* 'BYMONTH rrule) (list 11)))
|
||||
(should (equal (ical:rrule-by* 'BYDAY rrule) (list '(4 . 4))))
|
||||
(should (equal summary "American Thanksgiving"))))
|
||||
|
||||
(dit:parse-test
|
||||
|
|
@ -1030,13 +1030,13 @@ SOURCE, if given, should be a symbol; it is used to name the test."
|
|||
:tests
|
||||
(ical:with-component (car parsed)
|
||||
((ical:dtstart :value dtstart)
|
||||
(ical:rrule :value recur-value)
|
||||
(ical:rrule :value rrule)
|
||||
(ical:summary :value summary))
|
||||
(should (equal dtstart
|
||||
(calendar-nth-named-day 4 5 1 di:recurring-start-year)))
|
||||
(should (eq (ical:recur-freq recur-value) 'MONTHLY))
|
||||
(should (eq (ical:rrule-freq rrule) 'MONTHLY))
|
||||
;; day 3 is Wednesday, so offset of 2 means Friday (=5):
|
||||
(should (equal (ical:recur-by* 'BYDAY recur-value) (list '(5 . 4))))
|
||||
(should (equal (ical:rrule-by* 'BYDAY rrule) (list '(5 . 4))))
|
||||
(should (equal summary "Monthly committee meeting"))))
|
||||
|
||||
(dit:parse-test
|
||||
|
|
@ -1052,11 +1052,11 @@ SOURCE, if given, should be a symbol; it is used to name the test."
|
|||
:tests
|
||||
(ical:with-component (car parsed)
|
||||
((ical:dtstart :value dtstart)
|
||||
(ical:rrule :value recur-value)
|
||||
(ical:rrule :value rrule)
|
||||
(ical:exdate :values exdates)
|
||||
(ical:summary :value summary))
|
||||
(should (equal dtstart '(11 11 2024)))
|
||||
(should (eq (ical:recur-freq recur-value) 'WEEKLY))
|
||||
(should (eq (ical:rrule-freq rrule) 'WEEKLY))
|
||||
(should (equal exdates '((12 23 2024) (12 30 2024))))
|
||||
(should (equal summary "Reading group"))))
|
||||
|
||||
|
|
@ -1070,12 +1070,12 @@ SOURCE, if given, should be a symbol; it is used to name the test."
|
|||
:tests
|
||||
(ical:with-component (car parsed)
|
||||
((ical:dtstart :value dtstart)
|
||||
(ical:rrule :value recur-value)
|
||||
(ical:rrule :value rrule)
|
||||
(ical:summary :value summary))
|
||||
(should (equal dtstart (list 10 22 di:recurring-start-year)))
|
||||
(should (eq (ical:recur-freq recur-value) 'YEARLY))
|
||||
(should (equal (ical:recur-by* 'BYMONTH recur-value) (list 10 11 12)))
|
||||
(should (equal (ical:recur-by* 'BYMONTHDAY recur-value) (list 22)))
|
||||
(should (eq (ical:rrule-freq rrule) 'YEARLY))
|
||||
(should (equal (ical:rrule-by* 'BYMONTH rrule) (list 10 11 12)))
|
||||
(should (equal (ical:rrule-by* 'BYMONTHDAY rrule) (list 22)))
|
||||
(should (equal summary "Rake leaves"))))
|
||||
|
||||
(dit:parse-test
|
||||
|
|
|
|||
|
|
@ -388,21 +388,21 @@ test."
|
|||
|
||||
(ipt:parse/print-test
|
||||
"FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-1"
|
||||
:type icalendar-recur
|
||||
:type icalendar-rrule-value
|
||||
:parser icalendar-parse-value-node
|
||||
:printer icalendar-print-value-node
|
||||
:source rfc5545-sec3.3.10/1)
|
||||
|
||||
(ipt:parse/print-test
|
||||
"FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU;BYHOUR=8,9;BYMINUTE=30"
|
||||
:type icalendar-recur
|
||||
:type icalendar-rrule-value
|
||||
:parser icalendar-parse-value-node
|
||||
:printer icalendar-print-value-node
|
||||
:source rfc5545-sec3.3.10/2)
|
||||
|
||||
(ipt:parse/print-test
|
||||
"FREQ=DAILY;COUNT=10;INTERVAL=2"
|
||||
:type icalendar-recur
|
||||
:type icalendar-rrule-value
|
||||
:parser icalendar-parse-value-node
|
||||
:printer icalendar-print-value-node
|
||||
:source rfc5545-sec3.3.10/3)
|
||||
|
|
|
|||
|
|
@ -1383,7 +1383,7 @@ END:VTIMEZONE
|
|||
(ts-obs/onset (icr:tz-observance-on ts ict:tz-eastern)))
|
||||
(should (eq 'ical:daylight (ical:ast-node-type obs)))
|
||||
(should (equal dt onset))
|
||||
(should (equal end (ical:recur-until
|
||||
(should (equal end (ical:rrule-until
|
||||
(ical:with-property-of obs 'ical:rrule nil value))))
|
||||
(should (equal obs/onset ts-obs/onset)))
|
||||
|
||||
|
|
@ -1534,10 +1534,10 @@ SOURCE should be a symbol; it is used to name the test."
|
|||
,(format "Parse and evaluate recur-value example from `%s':\n%s"
|
||||
source doc)
|
||||
:tags ,tags
|
||||
(let* ((parsed (ical:parse-from-string 'ical:recur ,recur-string))
|
||||
(let* ((parsed (ical:parse-from-string 'ical:rrule-value ,recur-string))
|
||||
(recvalue (ical:ast-node-value parsed))
|
||||
(until (ical:recur-until recvalue))
|
||||
(count (ical:recur-count recvalue))
|
||||
(until (ical:rrule-until recvalue))
|
||||
(count (ical:rrule-count recvalue))
|
||||
(dtstart ,dtstart)
|
||||
(tzid
|
||||
(when (cl-typep dtstart 'ical:date-time)
|
||||
|
|
|
|||
Loading…
Reference in a new issue