Anyhoo: the agenda page at ndc2010.no doesn't seem to allow you to export an entire day in a single iCal file, so I decided to write a quick jQuery based bookmarklet to properly export a full day. Here's a video demonstration:
Click the video above to watch it embedded (best in full screen), or Watch in new window
In a nutshell: just go to the agenda page, log in, make sure your sessions for the target day are selected, then hit the bookmarklet to generate an aggregate iCal file.
And here's the bookmarklet. Drag it to your bookmark toolbar (if that works in your browser), or right click and save it as a bookmark from the context menu.
Update: Worth noting for Google Calendar (and possibly others) is that it will not import "duplicate" entries. This means that if you export a day plan, delete a few entries, then try to import the file again - it will throw a big bad error. At this point you can go back to the agenda page and export a new iCal file, which will have new event timestamp. Importing this will succeed without errors.
Update2 (June 15th, 3:11pm): Fixed a padding issue with dates when imported into Google Calendar, and replaced padding approach as a whole.
If you're curious about the source code, here it is in non-minified form. Some less-than pretty constructs are used, such as while-shift rather than join for Array expansion - to save processing memory, and avoid errors caused by such.
(function(){
function padl(s,n,c)
{
return new Array(1 + n - s.length).join(c) + s;
}
function makeCalendar()
{
var str = "";
while(events.length > 0)
{ str += (str == "" ? "" : "\r\n") + events.shift(); }
return "BEGIN:VCALENDAR" + "\r\n" +
"PRODID:-//Google Inc//Google Calendar 70.9054//EN" + "\r\n" +
"VERSION:2.0" + "\r\n" +
"CALSCALE:GREGORIAN" + "\r\n" +
"BEGIN:VTIMEZONE" + "\r\n" +
"TZID:Europe/Oslo" + "\r\n" +
"LAST-MODIFIED:20040526T134920Z" + "\r\n" +
"BEGIN:DAYLIGHT" + "\r\n" +
"DTSTART:20040328T010000" + "\r\n" +
"TZOFFSETTO:+0200" + "\r\n" +
"TZOFFSETFROM:+0000" + "\r\n" +
"TZNAME:CEST" + "\r\n" +
"END:DAYLIGHT" + "\r\n" +
"BEGIN:STANDARD" + "\r\n" +
"DTSTART:20041031T030000" + "\r\n" +
"TZOFFSETTO:+0100" + "\r\n" +
"TZOFFSETFROM:+0200" + "\r\n" +
"TZNAME:CET" + "\r\n" +
"END:STANDARD" + "\r\n" +
"END:VTIMEZONE" + "\r\n" +
str + "\r\n" +
"END:VCALENDAR";
};
function makeEvent(day, start, end, summary, description)
{
return "BEGIN:VEVENT" + "\r\n" +
"DTSTART;TZID=Europe/Oslo:201006" + day + "T" + start + "00Z" + "\r\n" +
"DTEND;TZID=Europe/Oslo:201006" + day + "T" + end + "00Z" + "\r\n" +
"DTSTAMP;TZID=Europe/Oslo:" + stamp + "\r\n" +
"DESCRIPTION:" + description + "\r\n" +
"LOCATION:Oslo Spektrum" + "\r\n" +
"SEQUENCE:0" + "\r\n" +
"STATUS:CONFIRMED" + "\r\n" +
"SUMMARY:" + summary + "\r\n" +
"TRANSP:OPAQUE" + "\r\n" +
"END:VEVENT";
};
var events = [];
var nowdt = new Date();
var stamp = nowdt.getFullYear() +
padl(nowdt.getMonth(), 2, "0") +
padl(nowdt.getDate(), 2, "0") + "T" +
padl(nowdt.getHours(), 2, "0") +
padl(nowdt.getMinutes(), 2, "0") +
padl(nowdt.getSeconds(), 2, "0") + "Z";
$(":checked").each(function()
{
var n = $(this).parents("tbody:first").find("div[id] h2.agenda:first");
var roughTime = n.html();
n = n.parents("tbody:first");
var e =
{
day: 15 + parseInt($(".agenda2:first").text().replace(/.*(\d).*/, "$1")),
track: roughTime.replace(/.*\((.*)\)/, "$1"),
time: roughTime.replace(/Time:\s*(.*) \(.*/, "$1").split(" - "),
subject: n.find(".ingress_agenda").text(),
author: n.find("tr td:nth-child(2) h2:first").text()
};
events.push(makeEvent(e.day, padl(e.time[0].replace(/:/, ""), 4, "0"), padl(e.time[1].replace(/:/, ""), 4, "0"), e.track + ": " + e.subject, e.author));
});
window.location = "data:text/calendar;," + escape(makeCalendar(events));
})()