MacDevCenter    
 Published on MacDevCenter (http://www.macdevcenter.com/)
 See this if you're having trouble printing code examples


Read iCal Data with Ruby

by Rod Schmidt
09/03/2003

Apple doesn't provide any APIs to read iCal's data, but you can do it yourself. This article presents a Ruby module to read iCal data and use in your own Ruby applications, including complete Cocoa applications written with RubyCocoa. In addition you'll learn how to read iCal data in any programming language you desire.

ICalReader

I needed a demo program for my presentation, Cocoa Programming with Ruby and RubyCocoa at the O'Reilly Mac OS X Conference. After running across another Mac DevCenter article, Transforming iCal Calendars with Java by Daniel Steinberg, I decided to write an application that simply displayed the events of the day from iCal. This meant I needed to write some Ruby code that would read iCal's data.

I ended up creating a Ruby module called ICal. ICal provides Ruby classes to read iCal data, the main one being ICalReader (I would have liked to have called the module iCal and the class iCalReader, but Ruby module and class names must start with a capital letter). ICalReader returns instances of another class called ICalEvent, which represents an event in the iCal calendars.

Currently, ICalReader provides three main methods for reading iCal data. These are:

These all use a private workhorse method called readEvents that performs the actual reading of the iCal data. This method is only invoked the first time events are asked for. After that all the events are in memory and the reader simply has to search through them to retrieve the events requested.

How it Works

All the data for iCal is stored in .ics files in ~/Library/Calendars. There is one .ics file for each calendar you have created. The first thing ICalReader does when you create it is compile a list of all these files.

Mac OSX Conference

Session by Rod Schmidt:
Cocoa Programming with Ruby and RubyCocoa

Using the standard development tools on Mac OS X, ProjectBuilder and InterfaceBuilder, this session will take you through building a simple Cocoa app using the Ruby language and the open-source project, RubyCocoa. The resulting app will be a full fledged Cocoa application that looks and feels just like applications written in Objective-C, except you get all the benefits of using Ruby, including blocks, iterators, a more conventional syntax, and garbage collection.

O'Reilly Mac OS X Conference
October 27-30, 2003
Santa Clara, CA


Each file contains all the events for that calendar and is simply a text file with the data in a specific format. This format is actually the iCalendar standard. You can find all the specs on this format at http://www.ietf.org/rfc/rfc2245.txt. Since it's a text file, you can use any language or method you want to read the file. We'll be taking advantage of Ruby's built-in support for regular expressions to parse the file.

Each event begins with a line that starts with BEGIN:VEVENT, and each event ends with a line that starts with END:VEVENT. readEvent simply goes through each calendar file, reads all the lines for an event and passes the lines to another method called parseEvent. parseEvent creates a new event, parses the lines for that event, and extracts the event's attributes.

The event's description is extracted by looking for a line that starts with SUMMARY:. Likewise the start date is extracted from the line that starts with DTSTART; event recurrence rules can be extracted from the line that starts with RRULE:. This is all done with Ruby's regular expression abilities and is pretty simple. Definitely itís a lot simpler than writing a full-blown parser. I've glossed over a lot of details and there are a lot more attributes that ICalEvent could glean. The iCalendar spec has details galore on all the possible data that's available.

How to Use It

To use the ICal module simply require it in your code:

require 'ICal'

Or you can just prefix any reference to the ICalReader class with ICal::. Next, you need to create an instance of ICalReader like so:

ical = ICalReader.new

Once you have an instance you can get a list of today's events with the following:

ical.todaysEvents

This will return a list of ICalEvent objects sorted by start time. You can then call the following accessor methods to get the attributes of the event:

ical.startDate
ical.startTime
ical.summary

Here's how you would print all the events scheduled for today:

ical = ICal::ICalReader.new
ical.todaysEvents do |event|
    puts "#{ical.startTime} - #{ical.summary}"
end

Obtaining ICalReader

You can get the source code for the ICal Ruby module from http://www.infinitenil.com/developers.html. There you will find a link to download iCal.rb. This is the source code for the ICal module. You are free to modify it and use it however you wish. Keep in mind this is still an early work in progress and needs quite a bit of work to be a complete iCal reader. I would love to hear back from any of you who find it useful, and how you're using it.

Rod Schmidt is a software developer in Salt Lake City, Utah and has been a professional developer for over 12 years.


Return to the Mac DevCenter

Copyright © 2009 O'Reilly Media, Inc.