Add per-entry timezone support for icalendar export
* lisp/ox-icalendar.el (org-icalendar-entry): Look for a "TIMEZONE" property. (org-icalendar--vevent, org-icalendar--vtodo): Accept additional timezone argument. (org-icalendar-convert-timestamp): Change parameter name to "tz", and accept a wider variety of values. * doc/org.texi: Mention in manual.
This commit is contained in:
parent
6a590738b1
commit
42458e682d
13
doc/org.texi
13
doc/org.texi
|
@ -14162,9 +14162,10 @@ and write it to @code{org-icalendar-combined-agenda-file} file name.
|
|||
@cindex property, SUMMARY
|
||||
@cindex property, DESCRIPTION
|
||||
@cindex property, LOCATION
|
||||
The iCalendar export back-end includes SUMMARY, DESCRIPTION and LOCATION
|
||||
properties from the Org entries when exporting. To force the back-end to
|
||||
inherit the LOCATION property, configure the
|
||||
@cindex property, TIMEZONE
|
||||
The iCalendar export back-end includes SUMMARY, DESCRIPTION, LOCATION and
|
||||
TIMEZONE properties from the Org entries when exporting. To force the
|
||||
back-end to inherit the LOCATION property, configure the
|
||||
@code{org-use-property-inheritance} variable.
|
||||
|
||||
When Org entries do not have SUMMARY, DESCRIPTION and LOCATION properties,
|
||||
|
@ -14173,6 +14174,12 @@ derives the description from the body of the Org item. The
|
|||
@code{org-icalendar-include-body} variable limits the maximum number of
|
||||
characters of the content are turned into its description.
|
||||
|
||||
The TIMEZONE property can be used to specify a per-entry time zone, and will
|
||||
be applied to any entry with timestamp information. Time zones should be
|
||||
specified as per the IANA time zone database format, e.g.@: ``Asia/Almaty''.
|
||||
Alternately, the property value can be ``UTC'', to force UTC time for this
|
||||
entry only.
|
||||
|
||||
Exporting to iCalendar format depends in large part on the capabilities of
|
||||
the destination application. Some are more lenient than others. Consult the
|
||||
Org mode FAQ for advice on specific applications.
|
||||
|
|
|
@ -106,11 +106,14 @@ You can use =ob-scala.el= as packaged in scala-mode, available from the
|
|||
MELPA repository.
|
||||
|
||||
** New features
|
||||
*** iCalendar export respects a TIMEZONE property
|
||||
Set the TIMEZONE property on an entry to specify a time zone for that
|
||||
entry only during iCalendar export. The property value should be
|
||||
specified as in "Europe/London".
|
||||
*** ~org-attach~ can move directory contents
|
||||
When setting a new directory for an entry, org-attach offers to move
|
||||
files over from the old directory. Using a prefix arg will reset the
|
||||
directory to old, ID based one.
|
||||
|
||||
*** New Org duration library
|
||||
This new library implements tools to read and print time durations in
|
||||
various formats (e.g., "H:MM", or "1d 2h 3min"...).
|
||||
|
|
|
@ -341,7 +341,7 @@ A headline is blocked when either
|
|||
(1- (length org-icalendar-date-time-format))) ?Z))
|
||||
|
||||
(defvar org-agenda-default-appointment-duration) ; From org-agenda.el.
|
||||
(defun org-icalendar-convert-timestamp (timestamp keyword &optional end utc)
|
||||
(defun org-icalendar-convert-timestamp (timestamp keyword &optional end tz)
|
||||
"Convert TIMESTAMP to iCalendar format.
|
||||
|
||||
TIMESTAMP is a timestamp object. KEYWORD is added in front of
|
||||
|
@ -352,8 +352,11 @@ Also increase the hour by two (if time string contains a time),
|
|||
or the day by one (if it does not contain a time) when no
|
||||
explicit ending time is specified.
|
||||
|
||||
When optional argument UTC is non-nil, time will be expressed in
|
||||
Universal Time, ignoring `org-icalendar-date-time-format'."
|
||||
When optional argument TZ is non-nil, timezone data time will be
|
||||
added to the timestamp. It can be the string \"UTC\", to use UTC
|
||||
time, or a string in the IANA TZ database
|
||||
format (e.g. \"Europe/London\"). In either case, the value of
|
||||
`org-icalendar-date-time-format' will be ignored."
|
||||
(let* ((year-start (org-element-property :year-start timestamp))
|
||||
(year-end (org-element-property :year-end timestamp))
|
||||
(month-start (org-element-property :month-start timestamp))
|
||||
|
@ -387,8 +390,9 @@ Universal Time, ignoring `org-icalendar-date-time-format'."
|
|||
(concat
|
||||
keyword
|
||||
(format-time-string
|
||||
(cond (utc ":%Y%m%dT%H%M%SZ")
|
||||
(cond ((string-equal tz "UTC") ":%Y%m%dT%H%M%SZ")
|
||||
((not with-time-p) ";VALUE=DATE:%Y%m%d")
|
||||
((stringp tz) (concat ";TZID=" tz ":%Y%m%dT%H%M%S"))
|
||||
(t (replace-regexp-in-string "%Z"
|
||||
org-icalendar-timezone
|
||||
org-icalendar-date-time-format
|
||||
|
@ -396,7 +400,10 @@ Universal Time, ignoring `org-icalendar-date-time-format'."
|
|||
;; Convert timestamp into internal time in order to use
|
||||
;; `format-time-string' and fix any mistake (i.e. MI >= 60).
|
||||
(encode-time 0 mi h d m y)
|
||||
(and (or utc (and with-time-p (org-icalendar-use-UTC-date-time-p)))
|
||||
(and (or (string-equal tz "UTC")
|
||||
(and (null tz)
|
||||
with-time-p
|
||||
(org-icalendar-use-UTC-date-time-p)))
|
||||
t)))))
|
||||
|
||||
(defun org-icalendar-dtstamp ()
|
||||
|
@ -545,7 +552,8 @@ inlinetask within the section."
|
|||
contents 0 (min (length contents)
|
||||
org-icalendar-include-body))))
|
||||
(org-icalendar-include-body (org-trim contents)))))))
|
||||
(cat (org-icalendar-get-categories entry info)))
|
||||
(cat (org-icalendar-get-categories entry info))
|
||||
(tz (org-element-property :TIMEZONE entry)))
|
||||
(concat
|
||||
;; Events: Delegate to `org-icalendar--vevent' to generate
|
||||
;; "VEVENT" component from scheduled, deadline, or any
|
||||
|
@ -556,14 +564,14 @@ inlinetask within the section."
|
|||
org-icalendar-use-deadline)
|
||||
(org-icalendar--vevent
|
||||
entry deadline (concat "DL-" uid)
|
||||
(concat "DL: " summary) loc desc cat)))
|
||||
(concat "DL: " summary) loc desc cat tz)))
|
||||
(let ((scheduled (org-element-property :scheduled entry)))
|
||||
(and scheduled
|
||||
(memq (if todo-type 'event-if-todo 'event-if-not-todo)
|
||||
org-icalendar-use-scheduled)
|
||||
(org-icalendar--vevent
|
||||
entry scheduled (concat "SC-" uid)
|
||||
(concat "S: " summary) loc desc cat)))
|
||||
(concat "S: " summary) loc desc cat tz)))
|
||||
;; When collecting plain timestamps from a headline and its
|
||||
;; title, skip inlinetasks since collection will happen once
|
||||
;; ENTRY is one of them.
|
||||
|
@ -581,7 +589,7 @@ inlinetask within the section."
|
|||
((t) t)))
|
||||
(let ((uid (format "TS%d-%s" (cl-incf counter) uid)))
|
||||
(org-icalendar--vevent
|
||||
entry ts uid summary loc desc cat))))
|
||||
entry ts uid summary loc desc cat tz))))
|
||||
info nil (and (eq type 'headline) 'inlinetask))
|
||||
""))
|
||||
;; Task: First check if it is appropriate to export it. If
|
||||
|
@ -595,7 +603,7 @@ inlinetask within the section."
|
|||
(not (org-icalendar-blocked-headline-p
|
||||
entry info))))
|
||||
((t) (eq todo-type 'todo))))
|
||||
(org-icalendar--vtodo entry uid summary loc desc cat))
|
||||
(org-icalendar--vtodo entry uid summary loc desc cat tz))
|
||||
;; Diary-sexp: Collect every diary-sexp element within ENTRY
|
||||
;; and its title, and transcode them. If ENTRY is
|
||||
;; a headline, skip inlinetasks: they will be handled
|
||||
|
@ -626,7 +634,7 @@ inlinetask within the section."
|
|||
contents))))
|
||||
|
||||
(defun org-icalendar--vevent
|
||||
(entry timestamp uid summary location description categories)
|
||||
(entry timestamp uid summary location description categories timezone)
|
||||
"Create a VEVENT component.
|
||||
|
||||
ENTRY is either a headline or an inlinetask element. TIMESTAMP
|
||||
|
@ -635,7 +643,8 @@ is the unique identifier for the event. SUMMARY defines a short
|
|||
summary or subject for the event. LOCATION defines the intended
|
||||
venue for the event. DESCRIPTION provides the complete
|
||||
description of the event. CATEGORIES defines the categories the
|
||||
event belongs to.
|
||||
event belongs to. TIMEZONE specifies a time zone for this event
|
||||
only.
|
||||
|
||||
Return VEVENT component as a string."
|
||||
(org-icalendar-fold-string
|
||||
|
@ -645,8 +654,8 @@ Return VEVENT component as a string."
|
|||
(concat "BEGIN:VEVENT\n"
|
||||
(org-icalendar-dtstamp) "\n"
|
||||
"UID:" uid "\n"
|
||||
(org-icalendar-convert-timestamp timestamp "DTSTART") "\n"
|
||||
(org-icalendar-convert-timestamp timestamp "DTEND" t) "\n"
|
||||
(org-icalendar-convert-timestamp timestamp "DTSTART" nil timezone) "\n"
|
||||
(org-icalendar-convert-timestamp timestamp "DTEND" t timezone) "\n"
|
||||
;; RRULE.
|
||||
(when (org-element-property :repeater-type timestamp)
|
||||
(format "RRULE:FREQ=%s;INTERVAL=%d\n"
|
||||
|
@ -664,7 +673,7 @@ Return VEVENT component as a string."
|
|||
"END:VEVENT"))))
|
||||
|
||||
(defun org-icalendar--vtodo
|
||||
(entry uid summary location description categories)
|
||||
(entry uid summary location description categories timezone)
|
||||
"Create a VTODO component.
|
||||
|
||||
ENTRY is either a headline or an inlinetask element. UID is the
|
||||
|
@ -672,6 +681,7 @@ unique identifier for the task. SUMMARY defines a short summary
|
|||
or subject for the task. LOCATION defines the intended venue for
|
||||
the task. DESCRIPTION provides the complete description of the
|
||||
task. CATEGORIES defines the categories the task belongs to.
|
||||
TIMEZONE specifies a time zone for this TODO only.
|
||||
|
||||
Return VTODO component as a string."
|
||||
(let ((start (or (and (memq 'todo-start org-icalendar-use-scheduled)
|
||||
|
@ -690,11 +700,11 @@ Return VTODO component as a string."
|
|||
(concat "BEGIN:VTODO\n"
|
||||
"UID:TODO-" uid "\n"
|
||||
(org-icalendar-dtstamp) "\n"
|
||||
(org-icalendar-convert-timestamp start "DTSTART") "\n"
|
||||
(org-icalendar-convert-timestamp start "DTSTART" nil timezone) "\n"
|
||||
(and (memq 'todo-due org-icalendar-use-deadline)
|
||||
(org-element-property :deadline entry)
|
||||
(concat (org-icalendar-convert-timestamp
|
||||
(org-element-property :deadline entry) "DUE")
|
||||
(org-element-property :deadline entry) "DUE" nil timezone)
|
||||
"\n"))
|
||||
"SUMMARY:" summary "\n"
|
||||
(and (org-string-nw-p location) (format "LOCATION:%s\n" location))
|
||||
|
|
Loading…
Reference in New Issue