Org-Mode iCalendar Import with Conversion to Floating Times

In an earlier blog post I wrote about using Emacs Org mode for calendaring, and exporting iCalendar files with TIMEZONE information (including “VTIMEZONE” definitions, as specified by RFC 5545). Another side of the picture is importing from iCalendar into Org, and in this post I introduce a little Ruby script I recently finished writing for that purpose.

I don't think I'm the first person to have written a half-baked script for iCalendar-to-Org import, but the special requirement I had was that I wanted to be able to interpret “DATE WITH UTC TIME” values in a non-standard way, and convert them into “floating” times (without time zone information).

For several years I used the Calendar application on Symbian phones, and there was neither a way to specify a “floating” time, nor could you select a specific time zone for an appointment. Consequently, I entered all entries in terms of a single time zone, and avoided ever changing zones, even temporarily. I had two sets of iCalendar files, ones with entries entered in the Europe/Helsinki time zone, and another set entered with respect to Europe/Oslo. The files themselves contained no time zone information.

To get a NotDeft-searchable record of where I've been and what I've done, I wanted a conversion program capable of correctly dealing with such files. The program would take a set of iCalendar input files and a single time zone name as an argument, and convert any “DATE WITH UTC TIME” values into floating times with respect to the argument time zone, and then output Org entries.

My input files would also contain “DATE” values in some cases (depending on the Symbian Calendar software version), but those are already floating by nature, translating directly into Org dates. I haven't tried the script with other time value formats, but the idea would be to have any time zone designators in “DATE WITH LOCAL TIME AND TIME ZONE REFERENCE” values be preserved in Org TIMEZONE properties, in cases where there is no conflicting information for a single entry (i.e., different “TZID” references for start and end times).

As an example, if we invoke

ics-to-org -q -f Europe/Oslo -i

with the input

BEGIN:VCALENDAR
VERSION:1.0
BEGIN:VEVENT
UID:a94133f2-017f-3318-85c8-cc99873ef472
SUMMARY:NWPT 2015
DTSTART:20151020T220000Z
DTEND:20151023T220000Z
X-EPOCAGENDAENTRYTYPE:APPOINTMENT
CLASS:PUBLIC
LOCATION:Reykjavik University
X-SYMBIAN-DTSTAMP:20150831T192356Z
SEQUENCE:0
X-METHOD:NONE
LAST-MODIFIED:20150831T192356Z
PRIORITY:5
X-SYMBIAN-LUID:272
TRANSP:0
X-USERDATA-INT:0
END:VEVENT
END:VCALENDAR

we get

* NWPT 2015
:PROPERTIES:
:SUMMARY: NWPT 2015
:LOCATION: Reykjavik University
:END:
<2015-10-21 Wed>--<2015-10-23 Fri>

and we end up with three full days, as originally entered—we have corrected the 20151020T220000Z and 20151023T220000Z time stamps, which are correct for Central European daylight saving time, but not for Reykjavik.

We can store the output in one of our org-agenda-files, and use org-agenda to navigate and view the exported data, where the above entry might appear as

Week-agenda (W43):
Monday     19 October 2015 W43
Tuesday    20 October 2015
  Diary:      Birth of the Báb
Wednesday  21 October 2015
  some-agenda:(1/3):  NWPT 2015
Thursday   22 October 2015
  some-agenda:(2/3):  NWPT 2015
Friday     23 October 2015
  some-agenda:(3/3):  NWPT 2015
Saturday   24 October 2015
Sunday     25 October 2015
  Diary:       3:00...... Daylight Saving Time Ends (CEST)

The Ruby script is available for

direct download
ics-to-org
cloning with Git
git clone https://tero.hasu.is/repos/icalendar-to-org.git

The script is known to work with Ruby version 2.3.3, Ruby tzinfo version 2.0.0, and Ruby icalendar version 2.5.2.