From 69b73bf2f8d80ac656385e483bac02e904078d5d Mon Sep 17 00:00:00 2001 From: Sylvain Chouleur Date: Fri, 10 Oct 2014 00:05:42 +0200 Subject: [PATCH] * icalendar.el: Support timezones without DST Some timezone does not define RRULE inside DAYLIGHT or STANDARD components because they do not have a daylight saving time. The RFC5545 specify that when no RRULE is specified, the observance is effective just once. The current icalendar code doesn't take care of the DTSTART so we can't apply the RFC here but fortunately, when timezone do not use RRULE, the TZOFFSETTO and TZOFFSETFROM values are always the same. Signed-off-by: Sylvain Chouleur --- ChangeLog | 5 +++++ lisp/calendar/icalendar.el | 53 ++++++++++++++++++++++++---------------------- 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index cdc2a7bae785..4e12c2b1663e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2014-11-09 Sylvain Chouleur + + * calendar/icalendar.el: Support timezone without daylight saving + time + 2014-11-08 Dani Moncayo * build-aux/msys-to-w32: simplify the initial over-engineered diff --git a/lisp/calendar/icalendar.el b/lisp/calendar/icalendar.el index 5f89318e139f..b024a38f8095 100644 --- a/lisp/calendar/icalendar.el +++ b/lisp/calendar/icalendar.el @@ -485,45 +485,48 @@ children." ALIST is an alist entry from a VTIMEZONE, like STANDARD. DST-P is non-nil if this is for daylight savings time. The strings are suitable for assembling into a TZ variable." - (let ((offset (car (cddr (assq 'TZOFFSETTO alist)))) - (rrule-value (car (cddr (assq 'RRULE alist)))) - (dtstart (car (cddr (assq 'DTSTART alist))))) + (let* ((offsetto (car (cddr (assq 'TZOFFSETTO alist)))) + (offsetfrom (car (cddr (assq 'TZOFFSETFROM alist)))) + (rrule-value (car (cddr (assq 'RRULE alist)))) + (dtstart (car (cddr (assq 'DTSTART alist)))) + (no-dst (equal offsetto offsetfrom))) ;; FIXME: for now we only handle RRULE and not RDATE here. - (when (and offset rrule-value dtstart) + (when (and offsetto dtstart (or rrule-value no-dst)) (let* ((rrule (icalendar--split-value rrule-value)) (freq (cadr (assq 'FREQ rrule))) (bymonth (cadr (assq 'BYMONTH rrule))) (byday (cadr (assq 'BYDAY rrule)))) ;; FIXME: we don't correctly handle WKST here. - (if (and (string= freq "YEARLY") bymonth) + (if (or no-dst (and (string= freq "YEARLY") bymonth)) (cons (concat ;; Fake a name. (if dst-p "DST" "STD") ;; For TZ, OFFSET is added to the local time. So, ;; invert the values. - (if (eq (aref offset 0) ?-) "+" "-") - (substring offset 1 3) + (if (eq (aref offsetto 0) ?-) "+" "-") + (substring offsetto 1 3) ":" - (substring offset 3 5)) + (substring offsetto 3 5)) ;; The start time. - (let* ((day (icalendar--get-weekday-number (substring byday -2))) - (week (if (eq day -1) - byday - (substring byday 0 -2)))) - ;; "Translate" the iCalendar way to specify the last - ;; (sun|mon|...)day in month to the tzset way. - (if (string= week "-1") ; last day as iCalendar calls it - (setq week "5")) ; last day as tzset calls it - (concat "M" bymonth "." week "." (if (eq day -1) "0" - (int-to-string day)) - ;; Start time. - "/" - (substring dtstart -6 -4) - ":" - (substring dtstart -4 -2) - ":" - (substring dtstart -2))))))))) + (unless no-dst + (let* ((day (icalendar--get-weekday-number (substring byday -2))) + (week (if (eq day -1) + byday + (substring byday 0 -2)))) + ;; "Translate" the iCalendar way to specify the last + ;; (sun|mon|...)day in month to the tzset way. + (if (string= week "-1") ; last day as iCalendar calls it + (setq week "5")) ; last day as tzset calls it + (concat "M" bymonth "." week "." (if (eq day -1) "0" + (int-to-string day)) + ;; Start time. + "/" + (substring dtstart -6 -4) + ":" + (substring dtstart -4 -2) + ":" + (substring dtstart -2)))))))))) (defun icalendar--parse-vtimezone (alist) "Turn a VTIMEZONE ALIST into a cons (ID . TZ-STRING). -- 2.1.1