# Batch duration fix for iCal events

A continuing theme of this blog has been the use of scripting to streamline my workflow and eliminate the repetitive tasks that computers keep thrusting upon me. Yesterday, I got another chance to save myself some time and boredom by writing a little script.

My older son’s baseball coach emailed the upcoming schedule to all the parents. There are about 20 games, so normally that would mean adding about 20 events to iCal. Even using the clipboard to paste in common text, adding 20 events to iCal is a painfully dull proposition. Fortunately, Mail has Data Detectors, which recognize dates and times in emails and can create a new iCal event from Mail in just a couple of clicks. Unfortunately, the coach sent the schedule in the form of an MS Word1 attachment, which the Data Detectors can’t see.

No matter. I opened the attachment in TextEdit, copied the schedule, pasted it into a new email message, and sent it to myself. The Data Detectors had no trouble with a plain text email, and I soon had the whole schedule in iCal. Since the Data Detectors use the subject of the email to set the summary of the iCal event, I made “Phillies Baseball” (Phillies is the team name) the subject of the email to myself.

There was, however, still one problem. iCal’s default duration for events is one hour, so although all the newly entered events had the right start time, they had an end time that was an hour early. (To ensure that fields are available for later games, the league limits its games to two hours.) Fixing 20 end times one by one would be both annoying and typo-prone; my solution was this little AppleScript:

1:  set sdate to date "Wednesday, April 1, 2009 12:00:00 AM"
2:  tell application "iCal"
3:    set baseball to every event in calendar "Home" whose summary is "Phillies Baseball" and start date > sdate
4:    repeat with game in baseball
5:      set stime to start date of game
6:      set etime to stime + (2 * hours)
7:      set end date of game to etime
8:    end repeat
9:  end tell


I didn’t actually type out the entire date string in Line 1. I just typed

set sdate to date "4/1/2009"


and the Script Editor lengthened it when the script was compiled.

Line 3, combined with the definition of sdate on Line 1, filters the events to get just this season’s baseball games. Lines 5–7 are where the real work is done. I find the syntax of Line 6 (which I learned from Erik’s Lab) more than a little weird. Writing a two-hour duration as 2 * hours is certainly compact—unusually compact for AppleScript—but it’s hardly English-like.

So now I have the baseball schedule in iCal and, after a sync, on my phone. The events are in my “Home” calendar, mixed in with vacation dates, birthday parties, doctor’s appointments, and so on. If I wanted to export the baseball schedule as an iCalendar (.ics) file for sharing with others, the first step would be to put all the games into their own calendar in iCal. This script—which is based on an import script I wrote some time ago—creates a new calendar called “Phillies” and copies the game schedule into it.

 1:  tell application "iCal"
2:    make new calendar with properties {name:"Phillies"}
3:
4:    set sdate to date "Wednesday, April 1, 2009 12:00:00 AM"
5:    set baseball to every event in calendar "Home" whose summary is "Phillies Baseball" and start date > sdate
6:
7:    repeat with game in baseball
8:      make new event at end of events of calendar "Phillies" with data game
9:    end repeat
10:
11:  end tell


The crux of the script is Line 8, which I consider to be quintessential AppleScript: verbose, convoluted, and thoroughly non-intuitive. Really, with data game?

Anyway, once this script is run, iCal will have a new “Phillies” calendar that can be exported to a file and used by anyone running an application with iCalendar support. I’m thinking that the next time I coach a team—probably basketball in the fall—I’ll send the parents an .ics file as well as a more conventional written schedule.

1. I have long since given up on the hope of Microsoft users recognizing that Office documents aren’t the best way to exchange information.