[MacTUG] University Holidays off the HR web page into iCal

Dani Roloson daroloso at mfcf.math.uwaterloo.ca
Sun Jan 4 15:38:28 EST 2009


Of course, we'd all back up iCal before running something like this.
HR could break this in a million ways.
Only tested under 10.5.
Enjoy responsibly.

Dani

============================== AppleScript code ==============================
-- pull the University Holidays off the HR web page
-- and put them into iCal -- Dani Roloson Jan/2009

set UWcalendar to "UW Holidays"
set UWholidayURL to "http://www.hr.uwaterloo.ca/pay/holidaylist.html"

-- change the following to the correct location
-- and do "chmod a+x filename" in Terminal
set myParse to "~/Desktop/HolidayParse.pl"
set inFile to "/tmp/UWHolidaysIN.txt"
set outFile to "/tmp/UWHolidaysOUT.txt"

set startTime to (current date)

tell application "Safari"
	make new document with properties {URL:UWholidayURL}
	delay 3 -- this is a delay to allow the page to start loading
	--wait till it's loaded
	set pageLoaded to false -- this initialises the pageLoaded variable that gets set below
	repeat while not pageLoaded -- keep doing this loop until loading complete
		if (do JavaScript "document.readyState" in document 1) is "complete" then
			set pageLoaded to true
		else
			delay 3 -- you can try adjusting this delay
		end if
	end repeat
	set myText to text of document 1
end tell

set writeToMe to (open for access inFile with write permission)
write (myText as text) to writeToMe starting at 0
close access writeToMe

-- parse the web page into lines like "Friday, December 25, 2009:Christmas"
do shell script myParse & " " & " <" & inFile & " >" & outFile

tell application "iCal"
	-- should probably delete the existing one
	if not (exists calendar UWcalendar) then
		make new calendar with properties {name:UWcalendar}
	end if

	set readFromMe to (open for access outFile)
	set myList to read readFromMe as {text} using delimiter {":", ASCII character 10} -- colon and line feed (UNIX file)
	close access readFromMe

	set myHolidayCount to ((count myList) / 2)
	repeat with myNum from 1 to myHolidayCount
		set myDateStr to (item ((2 * myNum) - 1) of myList)
		tell me -- iCal can't handle this so get AppleScript to do it
			set myDate to date myDateStr
		end tell

		set theSummary to (item (2 * myNum) of myList)
		set theDescription to "UW Holiday"
		tell calendar UWcalendar to make new event at end of events with properties {start date:myDate, end date:myDate, allday event:true, summary:theSummary, description:theDescription, url:UWholidayURL}
	end repeat
	activate
end tell

log ("Run took " & ((current date) - startTime) & " seconds.")

======================== HolidayParse.pl (Perl code) ========================
#!/usr/bin/perl
use strict;
use warnings;

# The relevant blocks of text from the web page look like:
#
# 2011
#
# New Year's Day
# Monday January 3
# Family Day
# Monday, February 21
# Good Friday
# Friday April 22
# ...
# Christmas
# Monday December 26
# Boxing Day
# Tuesday December 27
# Additional Days
# Wednesday December 28, Thursday December 29, Friday December 30

# The output generated is:
#
# Monday, January 3, 2011:New Year's Day
# Monday, February 21, 2011:Family Day
# Friday, April 22, 2011:Good Friday
# ...
# Monday, December 26, 2011:Christmas
# Tuesday, December 27, 2011:Boxing Day
# Wednesday, December 28, 2011:UW Holiday
# Thursday, December 29, 2011:UW Holiday
# Friday, December 30, 2011:UW Holiday

my $ynum = 0; # year number
my $dname;    # day of the week name
my $mname;    # month of the year name
my $dnum;     # day of the month number
my $prevline; # previous line

# The numbers in both hashes are just filler.
# Holidays don't happen on Saturday or Sunday
# (OK they do but UW gives us another day instead).
my %weekdays = (
	"Monday"    => 1,
	"Tuesday"   => 2,
	"Wednesday" => 3,
	"Thursday"  => 4,
	"Friday"    => 5
);
my %monthnames = (
	"January"   =>  1,
	"February"  =>  2,
	"March"     =>  3,
	"April"     =>  4,
	"May"       =>  5,
	"June"      =>  6,
	"July"      =>  7,
	"August"    =>  8,
	"September" =>  9,
	"October"   => 10,
	"November"  => 11,
	"December"  => 12
);

# Determine current year to skip past years.
# See http://perldoc.perl.org/functions/localtime.html
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
$year += 1900;

while (<STDIN>) {
	chomp;     # remove the newline
	s/^\s+//;  # remove leading whitespace
	s/\s+$//;  # remove trailing whitespace

	if ( /^\d\d\d\d$/ ) {  # consider a four-digit number to be a year
		$ynum = $_;
	} else {
		while (/(\w+)/g) { # examine each word on the line
			my $currentword = $1;
			if (exists($weekdays{$currentword}))
			{
				$dname = $currentword;
			}
			elsif (exists($monthnames{$currentword}))
			{
				$mname = $currentword;
			}
			elsif (($currentword =~ /^\d$/)
				|| ($currentword =~ /^\d\d$/))
			{
				$dnum = $currentword;

				# Ignore anything before a year is found
				# and anything less than the current year.
				# Change condition to ($ynum)
				# if you don't want to skip past years.
				if ($ynum >= $year) {
					print "$dname, $mname $dnum, $ynum:$prevline\n";
				}
			}
		}
	}
	s/^Additional Days$/UW Holiday/; # give these a better individual name
	$prevline = $_; # store the current line in case it's the holiday name
}


More information about the MacTUG mailing list