Files
hpr_website/www/eps/hpr1286/hpr1286_full_shownotes.html

133 lines
12 KiB
HTML
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta content="pandoc" name="generator" />
<meta content="width=device-width, initial-scale=1.0, user-scalable=yes" name="viewport" />
<meta content="Dave Morriss" name="author" />
<title>iCalendar Hacking (HPR Show 1286)</title>
<style type="text/css">code{white-space: pre;}</style>
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link href="http://hackerpublicradio.org/css/hpr.css" rel="stylesheet" />
</head>
<body id="home">
<div class="shadow" id="container"><header><h1 class="title">iCalendar Hacking (HPR Show 1286)</h1>
<h2 class="subtitle">Creating iCalendar rules by hand and with a Perl script</h2>
<h2 class="author">Dave Morriss</h2>
<hr /></header> <main id="maincontent"> <article> <header><h1>Table of Contents</h1><nav id="TOC"><ul>
<li><a href="#editors-note-2020-01-02">Editors Note 2020-01-02</a></li>
<li><a href="#the-problem">The Problem</a></li>
<li><a href="#research">Research</a></li>
<li><a href="#experiment-1">Experiment 1</a></li>
<li><a href="#experiment-2">Experiment 2</a></li>
<li><a href="#experiment-3">Experiment 3</a></li>
<li><a href="#conclusion">Conclusion</a></li>
<li><a href="#links">Links</a></li>
</ul></nav> </header><h2 id="editors-note-2020-01-02">Editors Note 2020-01-02</h2>
<p>The notes for this episode have been reformatted, particularly the long-form notes. This was done to make them more readable. Also, the original Git repository has been changed from <em>Gitorious</em> to <em>GitLab</em>.</p>
<p>In 2019 an iCalendar file was placed on the HPR server at <a href="http://hackerpublicradio.org/HPR_Community_News_schedule.ics">http://hackerpublicradio.org/HPR_Community_News_schedule.ics</a> which you can use in your own calendar application. The file contains the recording times of 12 months of Community News shows and is updated monthly.</p>
<h2 id="the-problem">The Problem</h2>
<p>Back in 2012 Ken Fallon tried to use Google Calendar to set up an event for the recording of the monthly <em>Community News</em> shows on HPR. He wanted to set these on the Saturday before the first Monday of the month. Surprisingly he didnt find a way to do this and ended up deleting the attempt.</p>
<p>I looked at the calendaring application I use: <em>Thunderbird</em> with the <em>Lightning</em> calendar plugin, to see if I could manage it. I also couldnt find a way.</p>
<p>This episode documents my journey to find a way to make the calendar entries we need.</p>
<h2 id="research">Research</h2>
<p>I was aware that calendars like Google Calendar and many more use iCalendar to represent and communicate events, and so I thought I would try and find out more. I have often wondered how iCalendar calendaring works, so I grabbed a copy of <strong>RFC 5545</strong> and absorbed enough to get a vague idea of how it defines recurrent entries. If youd like to read this yourself have a look at <a class="uri" href="http://www.ietf.org/rfc/rfc5545.txt">http://www.ietf.org/rfc/rfc5545.txt</a></p>
<p>There are two primary methods of defining recurrent events within iCalendar: <strong>RRULE</strong> and <strong>RDATE</strong>. The RRULE property is the more powerful of the two and the more complex. The description of RRULE is long and involved, but in the context of this problem I could see how to define the first Monday of every month:</p><pre><code>RRULE:FREQ=MONTHLY;BYDAY=1MO</code></pre><ul>
<li><strong><code>FREQ=MONTHLY</code></strong> simply means the rule repeats every month.</li>
<li><strong><code>BYDAY=1MO</code></strong> then means that every month the first Monday is selected.</li>
</ul>
<p>Most calendar applications are well able to deal with this sort of specification, and it seems to be the way in which most recurrent events are defined.</p>
<h2 id="experiment-1">Experiment 1</h2>
<p>However, this is not what we want. We need the Saturday before the first Monday, but the iCalendar syntax doesnt have any obvious way of subtracting 2 days to get the Saturday before, especially when it could be in the previous month.</p>
<p>The definition of the <strong>BYDAY</strong> rule part specifies a comma separated list of days of the week (MO, TU, WE, TH, FR, SA, SU). As we have seen these weekday specifications can also be preceded by a digit as in 1MO.</p>
<p>There is also a rule part <strong>BYSETPOS</strong> which modifies the BYDAY rule part. It is followed by a comma separated list of values which corresponds to the nth occurrence within the set of events specified by the rule.</p>
<p>This led me to believe that I could make a rule as follows:</p><pre><code>RRULE:FREQ=MONTHLY;BYDAY=SA,SU,1MO;BYSETPOS=1</code></pre><ul>
<li><strong><code>FREQ=MONTHLY</code></strong> as before means the rule repeats every month.</li>
<li><strong><code>BYDAY=SA,SU,1MO</code></strong> then means that every month the weekend before the first Monday is selected.</li>
<li><strong><code>BYSETPOS=1</code></strong> means to select the first first day of the group, the Saturday</li>
</ul>
<p>I was rather surprised to find that this actually worked, but soon discovered that it has a fatal flaw. If the three days in BYDAY are all in the same month it works fine, but if either the Saturday or Sunday are in the previous month it cant backtrack far enough and drops the event on the wrong day.</p>
<p>Even if this worked, I suspect many calendar applications couldnt define it anyway. <em>Thunderbird+Lightning</em> cannot for certain. The user interface is just not able to specify this amount of detail.</p>
<p>The following is the full iCalendar entry that I plugged into <em>Thunderbird</em>:</p><pre><code>BEGIN:VCALENDAR
PRODID:MyCal
VERSION:2.0
BEGIN:VEVENT
DTSTART:20130629T190000Z
DTEND:20130629T210000Z
LOCATION:mumble.openspeak.cc port: 64747
RRULE:FREQ=MONTHLY;BYDAY=SA,SU,1MO;BYSETPOS=1
SUMMARY:HPR Community News
END:VEVENT
END:VCALENDAR</code></pre><h2 id="experiment-2">Experiment 2</h2>
<p>However, I discovered there is an alternative way through the <strong>RDATE</strong> specification. With it you can define a number of events by pre-computing them. I was able to build a test calendar containing the next twelve <em>Community News</em> events (theres naturally a plug-in for Vim which recognises the syntax!), load it into <em>Thunderbird</em> and make it send out invitations.</p>
<p>In true Hacker style I wrote a Perl <a href="make_meeting.html">script</a><a class="footnote-ref" href="#fn1" id="fnref1"><sup>1</sup></a> to generate the necessary <strong>RDATE</strong> dates. The script uses the Perl module <em>Date::Calc</em> to perform date calculations and <em>Data::ICal</em> to generate iCalendar data.</p>
<p>Running the script in the following way:</p><pre><code>./make_meeting &gt; experiment2.ics</code></pre><p>generates a file containing 12 appointments that can be loaded into Thunderbird (and presumably any other iCalendar-based calendar).</p><pre><code>BEGIN:VCALENDAR
VERSION:2.0
PRODID:Data::ICal 0.20
X-WR-CALNAME:Hacker Public Radio
X-WR-TIMEZONE:Europe/London
BEGIN:VEVENT
DESCRIPTION:This is a test\, building an iCalendar file and loading it into
Thunderbird.\n-----------------------------------------\nMumble settings\
nServer Name: Anything you like\nServer Address: mumble.openspeak.cc \nPor
t: 64747\nName: Your name or alias is fine\n\nDon&#39;t have mumble\, setup in
structions can be found on our wiki -\nhttp://linuxbasix.com/tiki-index.ph
p?page=Linux+Basix+Mumble\n
DTEND:20130803T210000Z
DTSTART:20130803T190000Z
LOCATION:mumble.openspeak.cc port: 64747
RDATE;VALUE=DATE-TIME:20130803T190000Z
RDATE;VALUE=DATE-TIME:20130831T190000Z
RDATE;VALUE=DATE-TIME:20131005T190000Z
RDATE;VALUE=DATE-TIME:20131102T190000Z
RDATE;VALUE=DATE-TIME:20131130T190000Z
RDATE;VALUE=DATE-TIME:20140104T190000Z
RDATE;VALUE=DATE-TIME:20140201T190000Z
RDATE;VALUE=DATE-TIME:20140301T190000Z
RDATE;VALUE=DATE-TIME:20140405T190000Z
RDATE;VALUE=DATE-TIME:20140503T190000Z
RDATE;VALUE=DATE-TIME:20140531T190000Z
RDATE;VALUE=DATE-TIME:20140705T190000Z
SUMMARY:HPR Community News
END:VEVENT
END:VCALENDAR</code></pre><p>Thunderbirds event dialog will not let you edit the sub-events, just delete them, but the idea works, albeit in a rather clunky way.</p>
<p>I dont have access to many other calendaring systems, except for Korganizer. It sees the multiple dates as multiple discrete events rather than a single recurring event.</p>
<h2 id="experiment-3">Experiment 3</h2>
<p>Other calendaring systems that do not use iCalendar can handle this problem more effectively. For many years I have used a tool called <em>pcal</em> (<a class="uri" href="http://pcal.sourceforge.net/">http://pcal.sourceforge.net/</a>) that generates PostScript calendars which I print and hang on the wall. It can reliably specify the Saturday before the first Monday of each month with the expression:</p><pre><code>Saturday before first Monday in all HPR Community News (19:00 - 21:00)</code></pre><p>Another tool which can do this is <em>Remind</em> (<a class="uri" href="http://www.roaringpenguin.com/products/remind">http://www.roaringpenguin.com/products/remind</a>, <a class="uri" href="http://www.linuxjournal.com/article/3529">http://www.linuxjournal.com/article/3529</a>). With this the following expression achieves the required result:</p><pre><code>REM Mon 1 --2 AT 19:00 MSG HPR Community News (19:00 - 21:00)</code></pre><p>Remind comes with a tool which can generate iCalendar data, called <em>rem2ics</em>. It expects output from the <em>remind</em> command from which it generates data. The following example generates 12 meetings from the above reminder which is in the file <em>.reminders</em>.</p><pre><code>remind -s12 .reminders | TZ=UTC rem2ics -do &gt;reminders.ics</code></pre><p>The result uses the RDATE specification as discussed in Experiment 2, with the same result.</p><pre><code>BEGIN:VCALENDAR
VERSION:2.0
PRODID:http://mark.atwood.name/code/rem2ics rem2ics 0.93
BEGIN:VEVENT
UID:rem2ics.50a24176.3f5d.1@localhost
SUMMARY:HPR Community News (19\:00 - 21\:00)
DTSTART;TZID=UTC:20121103T190000
RDATE;TZID=UTC:20121103T190000,20121201T190000,20130105T190000,20130202T
190000,20130302T190000,20130330T190000,20130504T190000,20130601T190000,2
0130629T190000,20130803T190000,20130831T190000,20131005T190000
DTSTAMP:20121113Z124750Z
COMMENT: generated by rem2ics 0.93\n http://mark.atwood.name/code/rem2ic
s\n data[1]=|2012/11/03 * * * 1140 7\:00pm HPR Community News (19\:00 -
21\:00)|
END:VEVENT
END:VCALENDAR</code></pre><h2 id="conclusion">Conclusion</h2>
<p>It seems that the iCalendar specification <strong>should</strong> be able to generate the appointments we need using the compact RRULE specification. However, in the (admittedly small) sample of calendaring applications checked this does not seem to have been implemented properly.</p>
<p>Other tools that do not use iCalendar have less difficulty representing such events but are not as widely adopted.</p>
<p>If anyone has any ideas about how this problem could be solved more effectively then please let me know!</p>
<h2 id="links">Links</h2>
<ul>
<li>Detailed show notes: <a href="full_shownotes.html">full_shownotes.html</a></li>
<li>My <em>make_meeting</em> script for download - <a class="uri" href="https://gitlab.com/davmo/hprmisc/blob/master/make_meeting">https://gitlab.com/davmo/hprmisc/blob/master/make_meeting</a></li>
<li>Wikipedia iCalendar entry - <a class="uri" href="http://en.wikipedia.org/wiki/ICalendar">http://en.wikipedia.org/wiki/ICalendar</a></li>
<li>iCalendar RFC - <a class="uri" href="http://www.ietf.org/rfc/rfc5545.txt">http://www.ietf.org/rfc/rfc5545.txt</a></li>
<li>pcal PostScript calendar generator - <a class="uri" href="http://pcal.sourceforge.net/">http://pcal.sourceforge.net/</a></li>
<li>Remind - <a class="uri" href="http://www.roaringpenguin.com/products/remind">http://www.roaringpenguin.com/products/remind</a>, <a class="uri" href="http://www.linuxjournal.com/article/3529">http://www.linuxjournal.com/article/3529</a></li>
</ul><section class="footnotes"><hr />
<ol>
<li id="fn1">
<p>Note, this is a viewable HTML version of the script, but a downloadable version exists in a Git repository. See the <b>Links</b> section for details.<a class="footnote-back" href="#fnref1"></a></p>
</li>
</ol></section> </article> </main></div>
</body>
</html>