Function: icalendar-recur-nonexistent-date-time-p

icalendar-recur-nonexistent-date-time-p is a byte-compiled function defined in icalendar-recur.el.gz.

Signature

(icalendar-recur-nonexistent-date-time-p DT OBS-ONSET OBSERVANCE)

Documentation

Return non-nil if DT does not exist in a given OBSERVANCE.

Some local date-times do not exist in a given time zone. When switching from standard to daylight savings time, the local clock time jumps over a certain range of times. This function tests whether DT is one of those non-existent local times.

DT and OBS-ONSET should be icalendar-date-time values; OBS-ONSET should be the (local) time immediately at the onset of the OBSERVANCE. OBSERVANCE should be an icalendar-standard or icalendar-daylight component.

If this function returns t, then per RFC5545 Section 3.3.5, DT must be interpreted using the UTC offset in effect prior to the onset of OBSERVANCE. For example, at the switch from Standard to Daylight Savings time in US Eastern, the nonexistent time 2:30AM (Standard) must be re-interpreted as 3:30AM DST.

Source Code

;; Defined in /usr/src/emacs/lisp/calendar/icalendar-recur.el.gz
;; In RFC5545 Section 3.3.10, we read: "If the computed local start time
;; of a recurrence instance does not exist ... the time of the
;; recurrence instance is interpreted in the same manner as an explicit
;; DATE-TIME value describing that date and time, as specified in
;; Section 3.3.5." which in turn says:
;; "If, based on the definition of the referenced time zone, the local
;; time described occurs more than once (when changing from daylight to
;; standard time), the DATE-TIME value refers to the first occurrence of
;; the referenced time.  Thus, TZID=America/New_York:20071104T013000
;; indicates November 4, 2007 at 1:30 A.M. EDT (UTC-04:00).  If the
;; local time described does not occur (when changing from standard to
;; daylight time), the DATE-TIME value is interpreted using the UTC
;; offset before the gap in local times.  Thus,
;; TZID=America/New_York:20070311T023000 indicates March 11, 2007 at
;; 3:30 A.M. EDT (UTC-04:00), one hour after 1:30 A.M. EST (UTC-05:00)."
;; This quote from RFC 5545 is based on New York's 2007 timekeeping practice;
;; although that practice may change in the future, the example is still
;; valid for 2007.

;; TODO: verify that these functions are correct for time zones other
;; than US Eastern.
(defun icr:nonexistent-date-time-p (dt obs-onset observance)
  "Return non-nil if DT does not exist in a given OBSERVANCE.

Some local date-times do not exist in a given time zone.  When switching
from standard to daylight savings time, the local clock time jumps over
a certain range of times.  This function tests whether DT is one of those
non-existent local times.

DT and OBS-ONSET should be `icalendar-date-time' values; OBS-ONSET
should be the (local) time immediately at the onset of the
OBSERVANCE.  OBSERVANCE should be an `icalendar-standard' or
`icalendar-daylight' component.

If this function returns t, then per RFC5545 Section 3.3.5, DT must be
interpreted using the UTC offset in effect prior to the onset of
OBSERVANCE.  For example, at the switch from Standard to Daylight
Savings time in US Eastern, the nonexistent time 2:30AM (Standard) must
be re-interpreted as 3:30AM DST."
  (when (ical:daylight-component-p observance)
    (ical:with-component observance
        ((ical:tzoffsetfrom :value offset-from)
         (ical:tzoffsetto :value offset-to))
      (and (= (decoded-time-year dt) (decoded-time-year obs-onset))
           (= (decoded-time-month dt) (decoded-time-month obs-onset))
           (= (decoded-time-day dt) (decoded-time-day obs-onset))
           (let* ((onset-secs (+ (decoded-time-second obs-onset)
                                 (* 60 (decoded-time-minute obs-onset))
                                 (* 60 60 (decoded-time-hour obs-onset))))
                  (dt-secs (+ (decoded-time-second dt)
                              (* 60 (decoded-time-minute dt))
                              (* 60 60 (decoded-time-hour dt))))
                  (jumped (abs (- offset-from offset-to)))
                  (after-jumped (+ onset-secs jumped)))
             (and
              (<= onset-secs dt-secs)
              (< dt-secs after-jumped)))))))