Reading iCal in R
Nick Hood

Reading iCal in R

2021, May 26    

Being organised is an important habit for anyone in these days of scope creep – the tendency for more and more to be done as part of the job. We’re all trying to maximise our capacity, so eliminating duplication of effort is one way to avoid wasting time doing unnecessary admin. Productivity tools like email and calendars have replaced the memo and diary of pre-Internet days, but there are many brands and infrastructures, often competing with each other. The result can be that we end up keeping several email accounts, and several calendars with the inevitable double booking and confusion.

My policy is wherever possible to keep one master data source: documents are configuration managed and stored safely, checked out and checked in when updated and with a visible, reversible change history. Calendars for each project are aggregated in a suitable viewer from master files in iCal format, allowing them to be easily shared and syndicated.

Planning for next academic year, I wanted to display a simple GANTT chart for students of the overall course structure. This, because I had previously been duplicating weekly details from the master calendar. I wanted a way to automatically generate mini-GANTTs for each week in the Virtual Learning Environment (VLE) from the course calendar. Here’s how I did it: the VLE is written and published in Bookdown.

Fortunately, there is already a package for reading and manipulating iCal files. You may need to install this first.

> install.packages("calendar")

So, firstly we want to grab data from the iCal feed. This is the path to an .ics file or the ical data for the calendar: make sure it’s not just a link to a web interface for the calendar.

> mydat <- readLines("")

It’s worth checking that this has returned something useful: the head() function returns the first few lines and an iCal file should look something like this:

> head(mydat)
[1] "BEGIN:VCALENDAR"                     
[2] "VERSION:2.0"                         
[3] "METHOD:PUBLISH"                      
[4] "PRODID:-// calendars//EN"
[5] "CALSCALE:GREGORIAN"                  
[6] "BEGIN:VEVENT"       

We can use ic_dataframe() to organise this flat file into something more structured, again peeking in at the first few column header names in the data frame:

> mydf <- ic_dataframe(mydat)
> head(names(mydf))
[4] "UID"                "SEQUENCE"           "DTSTAMP"                          

Selecting the information you need from that is a matter of applying filters. A new data frame using the first 3 columns:

> set1 <- data.frame(mydf["DTSTART;VALUE=DATE"],mydf["SUMMARY"])
> head(set1)
1         2016-01-01         New Years Day
2         2016-03-25            Good Friday
3         2016-03-28          Easter Monday
4         2016-05-02 Early May bank holiday
5         2016-05-30    Spring bank holiday
6         2016-08-29    Summer bank holiday

Selecting only Jubilee holidays using the logical form of grep:

> set2 <- subset(set1,grepl("Jubilee",set1$SUMMARY))
> head(set2)
   DTSTART.VALUE.DATE                       SUMMARY
54         2022-06-03 Platinum Jubilee bank holiday

Adding new headings using setnames from the data.table library, then removing row numbers and displaying as a table.

setnames(set1, c("Date","Event name"))
set2 <- subset(set1,grepl("2022",set1$Date))
knitr::kable(set2[order(set2$From),], caption = '2022 Holiday Calendar', row.names = FALSE)

Which will yield a table in your book(down):

Table 1: 2022 Holiday Calendar

Date Holiday
2022-01-03 New Year’s Day
2022-04-15 Good Friday
2022-04-18 Easter Monday
2022-05-02 Early May bank holiday
2022-06-02 Spring bank holiday
2022-06-03 Platinum Jubilee bank holiday
2022-08-29 Summer bank holiday
2022-12-26 Boxing Day
2022-12-27 Christmas Day


I now have a way of automatically updating the calendar in the VLE for my course, by only having to rebuild the site after a change in the master calendar. This is hugely useful within my workflow and reduces the risk of divergence or error when there is more than one master. Next steps are to make this produce a GANTT chart.