Created
May 1, 2013 21:58
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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