Using the Python iCalendar Library

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.

Comments are closed.