Reading events from Google Calendar with Ruby
posted by Robbie Shade on 30 Oct 2011

The problem: We have a load of scheduled events which are currently duplicated in two places. They are first entered in the shared Google calendar, and secondly manually added to the events page at Additionally, past events must be manually moved to the page. Sad times.

The solution: Enter events once in Google calendar and use the API to retrieve events and wrap them in appropriate HTML containers.

The Google calendar API provides detailed documentation but our requirements are pretty simple. We don’t need fancy authentication as we’re parsing events from a publicly available calendar, and we don’t need to worry about creating, updating, or deleting records. We just need to retrieve two sets of events:

  • All events in the past for the past events page
  • All events in the future for the main events page

First thing to do, grab the URL of the public feed for the calendar from the calendar settings page. This will be something similar to

If you send an HTTP GET request to this URL you get XML returned containing every event ever on your calendar:

curl -s

An example feed is given in the Google calendar API reference.

By specifying parameters in the URL you can specify which events you want to be returned. For example, to get all future events, add the string “?futureevents=true” to the end of the URL. Many more examples are given in the Google calendar documentation.

curl -s

We want to parse the XML output of this call, pull out pertinent event details, and display them. We’re going to use components of the Ruby standard library to do this, namely net/http to communicate with Google calendar, and REXML to do the XML parsing.

require 'net/http'
require 'rexml/document'

url = ''

# get all future events, ordered by start time
url = url + "?futureevents=true&orderby=starttime"

xml_data = Net::HTTP.get_response(URI.parse(url)).body
doc = xml_data )

titles = []
content = []
doc.elements.each('feed/entry/title'){ |e| titles << e.text }
doc.elements.each('feed/entry/content'){ |e| content << e.text }

#print all events
titles.each_with_index do |title, idx|
  puts "Title: " + title + "\n\n"
  puts content[idx]
  puts "\n----\n\n"

Job done. If you want to display all past events, then you need to set the “start-max” parameter to be today’s date:

d =
url = url + '?start-max=' + d