Skip to content

Migrating from Other Libraries

Philipp Kewisch edited this page May 4, 2024 · 3 revisions

If you have previously been using other libraries, here are a few tips on how to change your code.

Peter Braden's ical.js (formerly node-ical)

This is https://github.com/peterbraden/ical.js. The library converts ICS into a custom object structure. Properties that appear more than once turn into arrays, properties that have parameters turn into objects with params and val members. The main object is keyed on the UID of the event.

  • jCal, the format ICAL.js mainly uses, has a more predictable object structure, but is also sometimes less convenient for simple getters.
  • Instead of operating on jCal directly (what ICAL.parse() returns), use the component and property wrappers with their lookup methods (e.g. new ICAL.Component(ICAL.parse(...))).
  • Recurrence for a RRULE is an iterator that starts on the first instance, if you want a specific range you need to skip the first ones.
  • ICAL.js' ICAL.RecurExpansion class will allow you to abstract away some of the recurrence calculations involving RRULEs, RDATEs and EXDATEs. If you'd like to stay on the same level, you can use ICAL.RecurIterator to get date instances of an RRULE.
node-ical jCal / ICAL.js
{
 "eb9e1bd2-ceba-499f-be77-f02773954c72": {
   "type": "VEVENT",
   "params": [],
   "uid": "eb9e1bd2-ceba-499f-be77-f02773954c72",
   "summary": "Event with an alarm",
   "description": "This is an event with an alarm.",
   "attendee": [
     {
       "params": {
         "PARTSTAT": "ACCEPTED"
       },
       "val": "MAILTO:[email protected]"
     },
     {
       "params": {
         "PARTSTAT": "ACCEPTED"
       },
       "val": "MAILTO:[email protected]"
     }
   ],
   "start": "2013-04-18T09:00:00.000Z",
   "end": "2013-04-18T10:00:00.000Z",
   "status": "CONFIRMED",
   "class": "PUBLIC",
   "transparency": "OPAQUE",
   "lastmodified": "2013-04-18T17:56:32.000Z",
   "dtstamp": "2013-04-18T17:56:32.000Z",
   "sequence": "3",
   "61170.614696615514": {
     "type": "VALARM",
     "params": [],
     "action": "DISPLAY",
     "trigger": {
       "params": {
         "RELATED": "START"
       },
       "val": "-PT5M"
     },
     "description": "Reminder"
   }
 }
}     
["vcalendar",
 [],
 [
   ["vevent",
     [
       [ "uid", {}, "text", "eb9e1bd2-ceba-499f-be77-f02773954c72" ],
       [ "summary", {}, "text", "Event with an alarm" ],
       [ "description", {}, "text", "This is an event with an alarm." ],
       [ "organizer", {}, "cal-address", "MAILTO:[email protected]" ],
       [ "attendee", { "partstat": "ACCEPTED" }, "cal-address", "MAILTO:[email protected]" ],
       [ "attendee", { "partstat": "ACCEPTED" }, "cal-address", "MAILTO:[email protected]" ],

       [ "dtstart", { "tzid": "America/Los_Angeles" }, "date-time", "2013-04-18T11:00:00" ],
       [ "dtend", { "tzid": "America/Los_Angeles" }, "date-time", "2013-04-18T12:00:00" ],
       [ "status", {}, "text", "CONFIRMED" ],
       [ "class", {}, "text", "PUBLIC" ],
       [ "transp", {}, "text", "OPAQUE" ],
       [ "last-modified", {}, "date-time", "2013-04-18T17:56:32Z" ],
       [ "dtstamp", {}, "date-time", "2013-04-18T17:56:32Z" ],
       [ "sequence", {}, "integer", 3 ]
     ],
     [
       ["valarm",
         [
           [ "action", {}, "text", "DISPLAY" ],
           [ "trigger", { "related": "START" }, "duration", "-PT5M" ],
           [ "description", {}, "text", "Reminder" ]
         ],
         []
        ]
      ]
    ]
  ]
] 

Here are some common ways to use the library:

node-ical jCal / ICAL.js
let data = ical.parseICS(input);
let firstEvent = [...Object.values(data)][0];
div.querySelector(".type").textContent = firstEvent.type;
div.querySelector(".title").textContent = firstEvent.summary;

let recdates = firstEvent.rrule.between(rangeStart, rangeEnd, true, () => true);
div.querySelector(".occurrences").textContent = recdates.map(dt => dt.toISOString()).join("\n");
let vcalendar = new ICAL.Component(ICAL.parse(input));
let vevent = vcalendar.getFirstSubcomponent("vevent");
let recur = vevent.getFirstPropertyValue("rrule");
let dtstart = vevent.getFirstPropertyValue("dtstart");
let iterator = recur.iterator(dtstart);

div.querySelector(".type").textContent = vevent.name;
div.querySelector(".title").textContent = vevent.getFirstProperty("summary");

let next, recdates = [];
while ((next = iterator.next()) && next.compare(rangeEnd) < 0) {
  if (next.compare(rangeStart) < 0) {
    continue;
  }
  recdates.push(next);
}
div.querySelector(".occurrences").textContent = recdates.map(dt => dt.toString()).join("\n");
Clone this wiki locally