An application I’m working on uses the icalendar library (http://codespeak.net/icalendar/) to generate an ICS file of upcoming events that can be linked to another calendar program (I’ve tried Outlook and Google Calendar). One problem I was having was that I was unable to generate time zone aware times. Mine were all naive – also called ‘floating’ times – that would appear the same regardless of the calendar program’s timezone.
What I was trying to do was to create a new time zone in the ICS file, and then append the TZID parameter to each date/time value. It was not happening.
So, I dug into the source code for icalendar. This library is well documented with tests, and I soon found a solution – include a tzinfo value when supplying the date/time and icalendar will convert it to UTC and append a ‘Z’ to the end of the time to indicate this. icalendar supplies a class called LocalTimezone that can be used for this purpose. I tried it, and it worked! Here’s a simplified version of my code:
from icalendar import Calendar, Event from datetime import datetime from icalendar import LocalTimezone cal = Calendar() cal.add('version', '2.0') cal.add('prodid', '-//test file//example.com//') cal.add('X-WR-CALNAME','Test Calendar ' ) lt = LocalTimezone() # we append the local timezone to each time so that icalendar will convert # to UTC in the output for ent in queryset: event = Event() event.add('summary', ent.event_name) event.add('dtstart', datetime.combine(ent.event_date,ent.start_time).replace(tzinfo=lt)) event.add('dtend', datetime.combine(ent.stop_date,ent.stop_time).replace(tzinfo=lt)) event.add('dtstamp', ent.updated_on.replace(tzinfo=lt)) event['uid'] = ent.pk # should probably use a better guid than just the PK event.add('priority', 5) cal.add_component(event) return cal
And this is a sample event from the output:
BEGIN:VEVENT DTEND: 20100714T184500Z DTSTAMP:20100714T185936Z DTSTART:20100719T174500Z PRIORITY:5 SUMMARY:Gateway Production UID:66 END:VEVENT
Note that my 1:45pm event in the US Eastern time zone (EDT) shows as 1745 in UTC.