Skip to content

Instantly share code, notes, and snippets.

@oz
Created May 1, 2013 21:58
Show Gist options
  • Save oz/5498721 to your computer and use it in GitHub Desktop.
Save oz/5498721 to your computer and use it in GitHub Desktop.
A memo of how ri_cal should be used to deal with timezones. It converts http://ambulante.com.mx's schedule to ICS format too.
#!/usr/bin/env ruby
# encoding: utf-8
#
# What:
#
# A memo of how ri_cal should be used to deal with timezones. It converts
# ambulante.com.mx's schedule to ICS format too.
#
# Deps:
#
# - nokogiri
# - tzinfo
# - ri_cal
# - chronic
#
# Usage:
#
# Grab the schedule's URL, then invoke with:
# curl $URL | ruby ambulante_ics.rb > Ambulante.ics
require 'nokogiri'
require 'tzinfo'
require 'ri_cal'
require 'chronic'
TZ = 'America/Mexico_City' # Times on the schedule are on this time zone
ENCODING = 'iso-8859-1' # website data isn't UTF8...
class Nokogiri::XML::Element
def join_children_text(join_string)
children.map(&:text).find_all { |txt| txt != '' }.join(join_string)
end
end
# Parse HTML DOM, and return a list of events.
def extract_events(doc)
doc.css('.lista_funciones tr')[1..-1].map do |event|
html_date, html_details, _, html_movie, html_place = event.children / 'td'
# Parse date
date = Chronic.parse html_date.text.sub(/\|\s*([\d:]+) HRS/, '\1')
# Parse pricing details, and additional informations
details = html_details.join_children_text(', ')
# Parse movie details
movie = html_movie.join_children_text(' (') + ')'
# Parse duration (default to 1 hour if not found)
if movie_duration = movie.match(/(\d+) min/)
duration_in_seconds = movie_duration[1].to_i * 60
else
duration_in_seconds = 60 * 60
end
# Parse location details
location = html_place.join_children_text(', ')
{
summary: movie.encode(ENCODING),
description: details.encode(ENCODING),
location: location.encode(ENCODING),
date_start: date,
date_end: date + duration_in_seconds,
}
end
end
# Generate ICS calendar from a list of events
def generate_ics(events)
RiCal.Calendar do |cal|
cal.default_tzid = TZ
events.each do |event|
cal.event do
summary event[:summary]
description event[:description]
location event[:location]
dtstart event[:date_start]
dtend event[:date_end]
end
end
end
end
events = extract_events Nokogiri::HTML(ARGF)
print generate_ics(events).to_s
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment