Subject: 23.4; icalendar import: daylight saving time

From: Christophe Deleuze <[email-masked]>
Date: Wed, 18 Sep 2013 14:54:01 +0200

[This is a small bug in icalendar.el.  A simple fix is provided.
Although tested on version 23.4, I checked the file icalendar.el hasn't
changed in current developpement version (downloaded for bazaar
repository on Sep 4th).]

* bug description

When importing an ics file into a diary file, date/times are not always
correctly converted from UTC to local time zone.

Example: let's import the provided mini.ics icalendar file, where
dates are in UTC (trailing 'Z'), on a system using the Europe/Paris
time zone.  This time zone has a time 2 hours ahead of UTC during
daylight saving and 1 hour ahead otherwise.

The file contains two events, the first one is planned on november 12
2013, from 12:15 to 14:00 UTC, the second one is planned on september
12 2013, from 8:00 to 9:45 UTC.

september 12 2013 is in daylight saving time period, while december 11
2013 is not.  The generated diary file (provided as mini.diary) shows
a 2 hours offset has been added to both events, while it should have
added a single hour offset to the second one.  It has been generated
on september 7 2013, during daylight saving time period.  Please note
that my emacs uses the european date display style, so that september
12 2013 is written as 12/9/2013 in the diary file.

* fix description

The function icalendar--decode-isodatetime in calendar/icalendar.el
calls (current-time-zone) to add current time zone offset when the ics
time is UTC.  However, the function is called without argument,
meaning the returned offset is the one applying at the time of
calling.

It should be called with the (UTC) date/time of the converted
date/time so that computed offset is the one in force at that precise
date/time.

The patch file icalendar.patch fixes the problem.  File
mini.diary-patched is the result of importing mini.ics with the
patched icalendar.el file.

* changelog

Small change in icalendar--decode-isodatetime.

*** calendar/icalendar.el.old	2013-09-04 11:17:18.000000000 +0200
--- calendar/icalendar.el	2013-09-04 11:20:29.000000000 +0200
***************
*** 562,570 ****
          (when (and (> (length isodatetimestring) 15)
                     ;; UTC specifier present
                     (char-equal ?Z (aref isodatetimestring 15)))
            ;; if not UTC add current-time-zone offset
!           (setq second (+ (car (current-time-zone)) second)))
          ;; shift if necessary
          (if day-shift
              (let ((mdy (calendar-gregorian-from-absolute
                          (+ (calendar-absolute-from-gregorian
--- 562,573 ----
          (when (and (> (length isodatetimestring) 15)
                     ;; UTC specifier present
                     (char-equal ?Z (aref isodatetimestring 15)))
            ;; if not UTC add current-time-zone offset
!           ;; current-time-zone should be called with actual UTC time
!           ;; (daylight saving at that time may differ to current one)
!           (setq second (+ (car (current-time-zone
!                                 (encode-time second minute hour day month year 0))) second)))
          ;; shift if necessary
          (if day-shift
              (let ((mdy (calendar-gregorian-from-absolute
                          (+ (calendar-absolute-from-gregorian