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)))