Fixing my calendar fixes

A couple of weeks ago, I posted a script that cleaned up the iCalendar (.ics) files provided by Southwest Airlines so they would show the information in a format that’s useful to me when I import them into my calendar. Today I learned that my cleaning needed some cleaning.

I made some reservations for later in the week, downloaded the .ics files, ran the swicsfix script to clean them, and then double-clicked the cleaned files to import them into my work calendar. The entries looked perfect in BusyCal

BusyCal entry

The summary and location fields were right and the alarm (for checking in online) was set properly to 1 day and 5 minutes before flight time. After the entries synced via iCloud, they looked generally OK in Fantastical on my iPhone

Fantastical iOS entry

I was a little suspicious of the “1 day before” setting for the alarm, but guessed that it looked that way because Fantastical was rounding to the nearest of its settings. A bit of testing with a dummy entry proved this guess correct—Fantastical would alarm 1 day and 5 minutes before flight time, despite what it said.

Fantastical on my Mac, though, had the entry all screwed up.

Fantastical OS X entry

The flights were entered as all-day events, and the check in alarms were set as if the flight were going to take off at midnight.

To figure out what was wrong, I looked at the .ics files and discovered these two suspicious lines:


They were in the original .ics file downloaded from Southwest and were passed through untouched by swicsfix. I should point out that Southwest calls the files I download “iCal compatible.”

Southwest calendar popup

What “iCal” would need with these Microsoft-specific lines is beyond me. Furthermore, it makes no sense for the ALLDAYEVENT part to be set to TRUE (which seemed the likely source of Fantastical’s error) or the BUSYSTATUS to be FREE. I decided the best thing for swicsfix to do was just delete them both. Here’s the new version:

 1:  #!/usr/bin/python
 3:  from icalendar import Calendar
 4:  import sys
 5:  from datetime import timedelta
 7:  for ics in sys.argv[1:]:
 8:    # Open the ics file and extract the event and alarm.
 9:    cal = Calendar.from_ical(open(ics).read())
10:    event = cal.walk('vevent')[0]
11:    alarm = event.walk('valarm')[0]
13:    # The last word in the location is the flight number.
14:    # The last word in the summary is the confirmation number.
15:    flight = event['location'].split()[-1]
16:    confirmation = event['summary'].split()[-1]
18:    # Erase the event's verbose description and rewrite its summary.
19:    event['description'] = ''
20:    event['summary'] = 'SW %s (%s)' % (flight, confirmation)
22:    # Get rid of the mistaken MS fields.
23:    try:
24:      del event['x-microsoft-cdo-alldayevent']
25:      del event['x-microsoft-cdo-busystatus']
26:    except KeyError:
27:      pass
29:    # Set the alarm to 24 hours, 5 minutes before the flight and
30:    # rewrite its description.
31:    alarm['trigger'].dt = timedelta(days=-1, minutes=-5)
32:    alarm['description'] = 'Check in SW %s (%s)' % (flight, confirmation)
34:    # Write the changes back to the original file.
35:    f = open(ics, 'w')
36:    f.write(cal.to_ical())
37:    f.close()

The addition is Lines 22–27. With that change, the BUSYSTATUS and ALLDAYEVENT lines were stripped from the .ics file and the entry looked perfect in Fantastical on the Mac.

Fantastical OS X entry fixed