Function: icalendar-recur-find-monthly-interval
icalendar-recur-find-monthly-interval is a byte-compiled function
defined in icalendar-recur.el.gz.
Signature
(icalendar-recur-find-monthly-interval TARGET DTSTART INTERVALSIZE &optional VTIMEZONE)
Documentation
Find a MONTHLY recurrence interval.
See icalendar-recur-find-interval for arguments' meanings.
Source Code
;; Defined in /usr/src/emacs/lisp/calendar/icalendar-recur.el.gz
(defun icr:find-monthly-interval (target dtstart intervalsize &optional vtimezone)
"Find a MONTHLY recurrence interval.
See `icalendar-recur-find-interval' for arguments' meanings."
(let* ((start-month (ical:date/time-month dtstart))
(start-year (ical:date/time-year dtstart))
;; we calculate in "absolute months", i.e., number of months
;; since the beginning of the Gregorian calendar, to make
;; finding the lower bound easier:
(start-abs-months (+ (* 12 (1- start-year)) (1- start-month)))
(target-month (ical:date/time-month target))
(target-year (ical:date/time-year target))
(target-abs-months (+ (* 12 (1- target-year)) (1- target-month)))
;; number of "absolute months" between start of dtstart's month
;; and start of target's month:
(nmonths (- target-abs-months start-abs-months))
;; the number of months after dtstart that is the closest integer
;; multiple of intervalsize months before target:
(lmonths (- nmonths (mod nmonths intervalsize)))
;; convert these "absolute months" back to Gregorian month and year:
(mod-month (mod (+ start-month lmonths) 12))
(low-month (if (zerop mod-month) 12 mod-month))
(low-year (+ (/ lmonths 12) start-year
;; iff we cross a year boundary moving forward in
;; time from start-month to target-month, we need
;; to add one to the year:
(if (<= start-month target-month) 0 1)))
;; and now we can use these to calculate the interval bounds:
(low (ical:make-date-time :year low-year :month low-month :day 1
:hour 0 :minute 0 :second 0 :tz vtimezone))
(high (ical:date/time-add low :month 1 vtimezone))
(next-low
(when (< 1 intervalsize)
(ical:date/time-add low :month intervalsize vtimezone))))
;; Return the bounds:
(icr:make-interval low high next-low)))