Function: icalendar-date-time-add

icalendar-date-time-add is a byte-compiled function defined in icalendar-utils.el.gz.

Signature

(icalendar-date-time-add DT DELTA &optional VTIMEZONE)

Documentation

Like decoded-time-add, but also updates weekday and time zone slots.

DT and DELTA should be icalendar-date-time values (decoded times), as in decoded-time-add. VTIMEZONE, if given, should be an icalendar-vtimezone. The resulting date-time will be given the offset determined by VTIMEZONE at the local time determined by adding DELTA to DT.

This function assumes that time units in DELTA larger than an hour should not affect the local clock time in the result, even when crossing an observance boundary in VTIMEZONE. This means that e.g. if DT is at
9AM daylight savings time on the day before the transition to standard
time, then the result of adding a DELTA of two days will be at 9AM standard time, even though this is not exactly 48 hours later. Adding a DELTA of 48 hours, on the other hand, will result in a time exactly 48 hours later, but at a different local time.

Source Code

;; Defined in /usr/src/emacs/lisp/calendar/icalendar-utils.el.gz
(defun ical:date-time-add (dt delta &optional vtimezone)
  "Like `decoded-time-add', but also updates weekday and time zone slots.

DT and DELTA should be `icalendar-date-time' values (decoded times), as
in `decoded-time-add'.  VTIMEZONE, if given, should be an
`icalendar-vtimezone'.  The resulting date-time will be given the offset
determined by VTIMEZONE at the local time determined by adding DELTA to
DT.

This function assumes that time units in DELTA larger than an hour
should not affect the local clock time in the result, even when crossing
an observance boundary in VTIMEZONE.  This means that e.g. if DT is at
9AM daylight savings time on the day before the transition to standard
time, then the result of adding a DELTA of two days will be at 9AM
standard time, even though this is not exactly 48 hours later.  Adding a
DELTA of 48 hours, on the other hand, will result in a time exactly 48
hours later, but at a different local time."
  (require 'icalendar-recur) ; for icr:tz-decode-time; avoids circular requires
  (declare-function icalendar-recur-tz-decode-time "icalendar-recur")

  (if (not vtimezone)
      ;; the simple case: we have no time zone info, so just use
      ;; `decoded-time-add':
      (let ((sum (decoded-time-add dt delta)))
        (ical:date-time-variant sum))
    ;; `decoded-time-add' does not take time zone shifts into account,
    ;; so we need to do the adjustment ourselves.  We first add the units
    ;; larger than an hour using `decoded-time-add', holding the clock
    ;; time fixed, as described in the docstring.  Then we add the time
    ;; units as a fixed number of seconds and re-decode the resulting
    ;; absolute time into the time zone.
    (let* ((cal-delta (make-decoded-time :year (or (decoded-time-year delta) 0)
                                         :month (or (decoded-time-month delta) 0)
                                         :day (or (decoded-time-day delta) 0)))
           (cal-sum (decoded-time-add dt cal-delta))
           (dt-w/zone (ical:date-time-variant cal-sum
                                              :tz vtimezone))
           (secs-delta (+ (or (decoded-time-second delta) 0)
                          (* 60 (or (decoded-time-minute delta) 0))
                          (* 60 60 (or (decoded-time-hour delta) 0))))
           (sum-ts (time-add (encode-time dt-w/zone) secs-delta)))
      (icalendar-recur-tz-decode-time sum-ts vtimezone))))