bennettscash
bennettscash
Back to tech - Using perl to import Lotus Notes calendar to iCal
Saturday, 18 July 2009
The last few hours has seen me back to my coding roots (yay!). I recently discovered that Lotus Notes 8.0, which is used at work for everything other than lunch, has the ability to export its calendar in iCalendar (.ics) format.
This set me thinking about how wonderful it would be to be able to have my work calendar on my iPhone, removing the necessity to rush from meeting to meeting via my desk to double-check where I’m meant to be going.
So I excitedly exported my Notes calendar to a .ics file on my corporate USB stick (that’s a story for another time), popped it into my my Macbook and imported the file into iCal.
Only to see no additional events in my calendar. I restarted iCal to see if it had gone crazy. Unfortunately not.
“Not to worry, I’ll do it via Google Calendar”. Looks like Google Calendar can’t read Lotus’ interpretation of the iCalendar “standard” either.
Bugger.
So I spent a couple of hours on Saturday morning fiddling with the contents of the calendar file to see if I could make it work.
Notes included a large number of timezone definitions. That probably makes some sense, but might not help matters. Then I discovered there were almost a dozen separate calendar sections within the XML file. Definitely not right. “I need to reformat this” I thought, firing up XCode and trying to think of the easiest way to implement it in perl.
I ended up with this, which works mostly - Although for my very large calendar (5 years, not 1) required an additional tweak. So if you’re suffering the same problem give it a go!
!/usr/bin/perl -w
use strict;
my $line;
my $event = 0;
my $endEvent = 0;
print<<END_PRINT;
BEGIN:VCALENDAR
X-WR-CALNAME:LotusNotes
PRODID:-//Apple Inc.//iCal 3.0//EN
CALSCALE:GREGORIAN
VERSION:2.0
METHOD:PUBLISH
BEGIN:VTIMEZONE
TZID:Australia/Canberra
BEGIN:STANDARD
TZOFFSETFROM:+1100
TZOFFSETTO:+1000
DTSTART:20080406T030000
RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1SU
TZNAME:EST
END:STANDARD
BEGIN:DAYLIGHT
TZOFFSETFROM:+1000
TZOFFSETTO:+1100
DTSTART:20081005T020000
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=1SU
TZNAME:EST
END:DAYLIGHT
END:VTIMEZONE
END_PRINT
while (<>) {
if (/^BEGIN\:VEVENT/) {
$event = 1;
} elsif (/END\:VEVENT/) {
$event = 0;
$endEvent = 1;
}
if ($event or $endEvent and not ( /^BEGIN\:VCALENDAR/ or /END:VCALENDAR/ )) {
$line = $_;
$line =~ s/\;TZID=(.)+\:/\;TZID=Australia\/Canberra:/g;
print $line;
}
$endEvent = 0;
}
print "END:VCALENDAR\n";
Simply run it from a terminal like so:
perl fileNameWithPastedCode.pl brokenNotesCalendar.ics > fixedNotesCalendar.ics
I mentioned a problem earlier - When run over my entire calendar file this didn’t change the effect of an import (even though it worked fine with a 12-month snapshot of my calendar). I don’t understand why, but when I opened the resulting file in TextWrangler the resulting file was double-spaced. Here’s what I did:
Changed the character format using TextWrangler to “Unix (LF)”:

Saved the file
Opened a terminal and ran the following:
grep -ve ^$ fixedNotesCalendar.ics
And it all worked!