VObject - An iCalendar and vCard Library

Author: Jeffrey Harris
Date: 2006-02-10
Open Source Applications Foundation logo

Start

You may have heard of vCard and vCalendar.

Bad Name

You probably asked yourself:

Versit

Blame it on the Versit consortium.

Standards

Who uses the various standards?

Syntax

These formats have similar, odd, syntax.

Not Invented Here

Attempting to avoid NIH syndrome, looked for existing options.

They tended to be:

Genesis

So I had a thought.

Jeffrey having a thought

Goal

A library for contact and event data.

Name

Isn't vobject a boring name?

Failed to avoid NIH

Lots of Python iCalendar code written simultaneously.

Features

iCalendar data structures

iCalendar maps nicely to XML.

BEGIN:VEVENT
DTSTART;TZID=US/Pacific:200602092000
END:VEVENT

<VEVENT>
  <DTSTART TZID="US/Pacific">200602092000</DTSTART>
</VEVENT>

xCalendar

Why didn't they just use XML?

Parsing

vobject parses iCalendar-style syntax

Simple data

At this point, the tree contains:

We want:

Transformation

Can they transform themselves?

Superman changing outfits

Behaviors

Items in the tree can be assigned behaviors.

Behaviors Continued

Once a behavior is applied, a component:

Behaviors provide a transformToNative method.

An ics file

Parsing example

>>> import vobject
>>> f = file('BayPiggies.ics')
>>> cal = vobject.readOne(f)

Working with trees

>>> ev = cal.vevent
>>> ev.summary
<SUMMARY{}BayPiggies>
>>> ev.summary.value
u'BayPiggies'

Datetimes and timezones

>>> start = cal.vevent.dtstart
>>> print start.value
2006-02-09 19:30:00-08:00
>>> tz = start.value.tzinfo
>>> tz
<tzicalvtz 'US/Pacific'>
>>> cal.vevent.dtend.value - start.value
datetime.timedelta(0, 5400)

Recurrence

>>> cal.vevent.rruleset
<dateutil.rrule.rruleset instance at 0x4e014c>
>>> for dt in cal.vevent.rruleset[:3]:
...    print dt
2006-02-09 19:30:00-08:00
2006-03-09 19:30:00-08:00
2006-04-13 19:30:00-07:00

iCalendar from scratch

Of course, you can go the other direction.

>>> import vobject
>>> cal = vobject.iCalendar()
>>> ev =   cal.add('vevent')
>>> start = ev.add('dtstart')

iCalendar from scratch (2)

>>> from datetime import datetime
>>> start.value = datetime(2006,2,9,7,30, tzinfo = tz)
>>> ev.add('summary').value = "BayPiggies"
>>> cal.prettyPrint()
 VCALENDAR
    VEVENT
       DTSTART: 2006-02-09 07:30:00-08:00
       SUMMARY: BayPiggies

Serializing

Walking through the output:

>>> lines = cal.serialize().splitlines()
>>> print '\n'.join(lines[0:3])
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//PYVOBJECT//NONSGML Version 1//EN

Serializing timezones

A VTIMEZONE is calculated from the tzinfo class.

>>> print '\n'.join(lines[3:12])
BEGIN:VTIMEZONE
TZID:US/Pacific
BEGIN:STANDARD
DTSTART:20001029T020000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
TZNAME:US/Pacific
TZOFFSETFROM:-0700
TZOFFSETTO:-0800
END:STANDARD

Generating required lines

UID is required, so VEVENT's behavior generated one.

>>> print '\n'.join(lines[20:])
BEGIN:VEVENT
UID:20060210T024827Z-20213@Wind
DTSTART;TZID=US/Pacific:20060209T073000
SUMMARY:BayPiggies
END:VEVENT
END:VCALENDAR

Areas for improvement