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:
- todaysEvents
- tomorrowsEvents
- eventsFor(date)
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.
|

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 its 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