One iCalendar to diff them all and in the python merge them

The One Ring python with calendars

One problem with progressing through a series of different PDA or smartphone platforms is that your data gets fragmented. As part of a general decrufting and consolidation of my data, i've been trying to merge the various iCalendar files i have (extension .ics) into a single, comprehensive, calendar. A Web search for a suitable utility didn't turn anything up, so i wrote one in python. I used it to merge components from all the older files that were missing in the newest file, to selectively update the properties of some existing components by the LAST-MODIFIED property, where an older calendar had newer content because two copies of the calendar had been in active use at the same time, and to strip out a few extraneous properties specific to earlier software or devices that exist in almost every component. More importantly, i used it to diff those files before doing the merges, to be sure of what was going to be changed.

The end result worked well for me, and i'm releasing it under the MIT License as free software.

It relies on the python icalendar package version 3+ and is compatible with python 2.7 (sorry, icalendar isn't python3k ready).

Download it here.

The rest is from the header:

This code requires that the icalendar python module be present. The icalendar module
is for parsing and serializing documents in the most recent revision of the iCalendar
format (http://www.ietf.org/rfc/rfc5545.txt), which is widely used as either native
file format or a supported format in calendaring and event-management software, including
the imaginatively named Apple iCal application and Google Calendar. iCalendar files
typically have extension .ics. See https://pypi.python.org/pypi/icalendar for the module.

This file provides a CalendarFile class that can be instantiated by calling
CalendarFile.from_file('some_file.ics')

The class provides some useful diff and merge methods:
.diff(): shows differences in both components (VEVENT, VJOURNAL, etc.) and component properties
.multi_diff(): shows differences in components between the calendar and all .ics in a directory
.merge(): adds components to this calendar found in the other, and possibly updates properties
.multi_merge(): adds components to this calendar found in all .ics files in a directory

Each takes another ics file or path (directory) as an argument. It also has a useful
.strip_field(field) method that removes all properties with name=field in the calendar.
Finally, the modified calendar can be written out with
.to_file('modified_file.ics')

Note that there are other, somewhat related packages around.
* merge-ics (https://code.google.com/p/merge-ics/) is no longer in development and only
supports VEVENTs (according to its own readme)
* pyICSParser (http://pythonhosted.org/pyICSParser) claims itself superior to the icalendar +
dateutils functionality, but does not appear to support conversion back to ics file format.
* vobject (http://vobject.skyhouseconsulting.com/) is another full-featured iCalendar library.
A diff script is provided.

There are examples for use at the end of the file, and the methods are documented.

It works correctly with the old ics calendars i have that were either from or converted from
files created by a handful of different PDA devices dating back to late 1999 as i used them to
make digital journal entries.

Alas, it may not work on your files. License provisions aside, if you do use this and find it
useful and/or buggy and/or you make improvements, i would appreciate hearing about it. I can
make no guarantees about bug fixes or revisions, but it's always possible.

The latest version can be found at http://www.inquisitive.org/calendarfile.