Function: icalendar-recur-refine-byweekno

icalendar-recur-refine-byweekno is a byte-compiled function defined in icalendar-recur.el.gz.

Signature

(icalendar-recur-refine-byweekno INTERVAL WEEKNOS &optional WEEKSTART VTIMEZONE)

Documentation

Resolve INTERVAL into a list of subintervals matching WEEKNOS.

WEEKNOS should be a list of values from a recurrence rule's BYWEEKNO=... clause, and WEEKSTART should be the value of its WKST=... clause (if any). See icalendar-recur for the possible values.

Source Code

;; Defined in /usr/src/emacs/lisp/calendar/icalendar-recur.el.gz
(defun icr:refine-byweekno (interval weeknos &optional weekstart vtimezone)
  "Resolve INTERVAL into a list of subintervals matching WEEKNOS.

WEEKNOS should be a list of values from a recurrence rule's
BYWEEKNO=... clause, and WEEKSTART should be the value of its
WKST=... clause (if any).  See `icalendar-recur' for the possible values."
  (let* ((sorted-weeknos (sort weeknos
                               :key (lambda (a) (if (< 0 a) a (+ 53 a)))))
         (interval-start (icr:interval-low interval))
         (curr-year (decoded-time-year interval-start))
         (interval-end (icr:interval-high interval))
         (end-year (decoded-time-year interval-end))
         (subintervals nil))
    (while curr-year
      ;; For each year in the interval...
      (dolist (wn sorted-weeknos)
        ;; ...the subinterval is one week long in the wn-th week
        (let* ((nth-wstart (ical:start-of-weekno wn curr-year weekstart))
               (low (ical:make-date-time :year (calendar-extract-year nth-wstart)
                                         :month (calendar-extract-month nth-wstart)
                                         :day (calendar-extract-day nth-wstart)
                                         :hour 0 :minute 0 :second 0
                                         :tz vtimezone))
               (high (ical:date/time-add low :day 7 vtimezone)))
          ;; "Clip" the subinterval bounds if they fall outside the
          ;; interval, as above.  This can happen often here because week
          ;; boundaries generally do not align with year boundaries.
          (when (ical:date/time< low interval-start)
            (setq low interval-start))
          (when (ical:date/time< interval-end high)
            (setq high interval-end))
          (when (and (ical:date-time<= interval-start low)
                     (ical:date-time< low high)
                     (ical:date-time<= high interval-end))
              (push (icr:make-interval low high) subintervals))))
      (setq curr-year (1+ curr-year))
      (when (<= end-year curr-year)
        ;; we're done:
        (setq curr-year nil)))
    (nreverse subintervals)))