I recently setup Voyager's Circulation Calendar for the next 6 months. That spans Spring Break, extended hours, and the Summer resulting in 118 exceptions. That's a lot to check for accuracy. I could probably have eliminated some of the redundancy in the exceptions by creating multiple calendars with sane defaults, but that'd probably add more complexity than what it's worth. So, I created a script to export a Voyager Circulation Calendar into Google Calendar so that you can better visual the results. Bonus features include calendar sharing - so others can verify its accuracy without needing access to Circulation in the SysAdmin module. Even better, Google's iCal support allows me to pull it into Outlook so even a Luddite is just a click away from looking up the calendar.
Check out the source on Github, which includes a readme.
require 'googlecalendar'
require 'active_record'
CONFIG = {
:start => {
:year => 2011,
:month => 3,
:day => 15
},
:end => {
:year => 2011,
:month => 8,
:day => 25
},
:database => {
:database => '',
:username => '',
:password => ''
},
:gcal => {
:email => '',
:password => ''
},
:calendar_id => 22
}
class Calendar < ActiveRecord::Base
set_table_name :calendar
set_primary_key :calendar_id
has_many :holidays
end
class Holiday < ActiveRecord::Base
set_table_name 'exception_calendar'
set_primary_key 'calendar_id' # Exception_calendar primary key is actually (:calendar_id, :exception_date)
belongs_to :calendar
end
ActiveRecord::Base.establish_connection(
:adapter => "oracle_enhanced",
:database => CONFIG[:database][:database],
:username => CONFIG[:database][:username],
:password => CONFIG[:database][:password]
)
hours = Calendar.find_by_sql("SELECT * FROM calendar WHERE calendar_id = #{CONFIG[:calendar_id]}")[0]
g = Googlecalendar::GData.new
g.login(CONFIG[:gcal][:email], CONFIG[:gcal][:password])
# Iterate over the date from start to end
(Date.new(CONFIG[:start][:year], CONFIG[:start][:month], CONFIG[:start][:day])..Date.new(CONFIG[:end][:year], CONFIG[:end][:month], CONFIG[:end][:day])).each do |current|
# Default to setting the open, close, and opened according to the calendar's default settings
case current.strftime('%A')
when 'Sunday'
open = hours.sunday_openhour
close = hours.sunday_closehour
opened = hours.sunday_open
when 'Monday'
open = hours.monday_openhour
close = hours.monday_closehour
opened = hours.monday_open
when 'Tuesday'
open = hours.tuesday_openhour
close = hours.tuesday_closehour
opened = hours.tuesday_open
when 'Wednesday'
open = hours.wednesday_openhour
close = hours.wednesday_closehour
opened = hours.wednesday_open
when 'Thursday'
open = hours.thursday_openhour
close = hours.thursday_closehour
opened = hours.thursday_open
when 'Friday'
open = hours.friday_openhour
close = hours.friday_closehour
opened = hours.friday_open
when 'Saturday'
open = hours.saturday_openhour
close = hours.saturday_closehour
opened = hours.saturday_open
end
# Check for an exception on this day.
holiday = hours.holidays.find(:first, :conditions=> "exception_date = '#{current.strftime('%Y-%m-%d 00:00:00')}'")
# If we have an exception, set open, close, and opened according to the exception
unless holiday.nil?
open = holiday.exception_openhour
close = holiday.exception_closehour
opened = holiday.exception_open
end
# Cast from types in database to String
open = open.to_s
close = close.to_s
opened = opened.to_s
if opened == 'Y'
# We're open
open = ' ' + open if open.length == 3 # Pad 3 digit hours (e.g. "930") with whitespace (e.g. " 930")
close = ' ' + close if close.length == 3 # Pad 3 digit hours (e.g. "930") with whitespace (e.g. " 930")
# Assumes the library always opens in the morning.
# e.g. "Open 2011-03-15 7:30am-9:30pm"
s = "Open #{current.strftime('%Y-%m-%d')} #{open[0..1]}:#{open[2..3]}am-#{(close[0..1].to_i - 12).to_s}:#{close[2..3]}pm"
else
# We're closed
# e.g. "Closed 2011-03-15"
s = "Closed #{current.strftime('%Y-%m-%d')}"
end
puts "Creating: #{s}"
# Add to default google calendar
#g.quick_add(s)
# Sleep so as not to be blocked by Google
#sleep(1)
end