iCal.js - iCalendar and vCard Parser

2.2.1 · active · verified Sun Apr 19

ical.js is a JavaScript library designed for parsing and manipulating iCalendar (RFC 5545) and vCard (RFC 6350) data, along with their JSON counterparts jCal (RFC 7265) and jCard (RFC 7095). The library is currently at version 2.2.1 and maintains an active development cycle, regularly releasing updates that include bug fixes, performance improvements, and TypeScript type enhancements. Originally ported from libical with a focus on web compatibility, it provides a robust, dependency-free solution for handling calendar and contact data. A key differentiator is its dual distribution, offering both ES6 modules for modern environments and a transpiled ES5 CommonJS build for broader compatibility, particularly in older browser script tags. It also offers an optional, separate bundle for comprehensive IANA timezone definitions, acknowledging their size and update frequency.

Common errors

Warnings

Install

Imports

Quickstart

Demonstrates parsing an iCalendar string, accessing the calendar component, and iterating through its event components to log event summaries, locations, start times, and handle recurring events.

import ICAL from "ical.js";

async function parseAndDisplayCalendar() {
  const icsData = `BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:-//Example Corp//NONSGML My Calendar//EN\nCALSCALE:GREGORIAN\nBEGIN:VEVENT\nUID:event1@example.com\nDTSTAMP:20230101T120000Z\nDTSTART:20230115T100000Z\nDTEND:20230115T110000Z\nSUMMARY:Team Meeting\nDESCRIPTION:Discuss Q1 planning and objectives.\nLOCATION:Conference Room A\nEND:VEVENT\nBEGIN:VEVENT\nUID:event2@example.com\nDTSTAMP:20230101T130000Z\nDTSTART:20230220T140000Z\nDURATION:PT1H30M\nSUMMARY:Project Deadline Review\nRRULE:FREQ=MONTHLY;COUNT=3\nEND:VEVENT\nEND:VCALENDAR`;

  try {
    const jcalData = ICAL.parse(icsData);
    const comp = new ICAL.Component(jcalData);

    console.log("Calendar events:");
    const events = comp.getAllSubcomponents('vevent');

    if (events.length === 0) {
      console.log("No events found.");
      return;
    }

    events.forEach((eventComp, index) => {
      const event = new ICAL.Event(eventComp);
      console.log(`\nEvent ${index + 1}:`);
      console.log(`  Summary: ${event.summary}`);
      console.log(`  Location: ${event.location || 'N/A'}`);
      console.log(`  Start: ${event.startDate.toString()}`);

      if (event.isRecurring()) {
        console.log(`  (Recurring Event - Rule: ${event.getFirstPropertyValue('rrule') ? event.getFirstPropertyValue('rrule').toString() : 'N/A'})`);
        const iterator = event.iterator();
        let occurrences = [];
        let next;
        // Get up to 5 occurrences
        for (let i = 0; i < 5 && (next = iterator.next()); i++) {
            occurrences.push(new ICAL.Time(next).toString());
        }
        if (occurrences.length > 0) {
            console.log(`  First 5 occurrences: ${occurrences.join(', ')}`);
        }
      } else {
        console.log(`  End: ${event.endDate.toString()}`);
      }
    });

  } catch (error) {
    console.error("Error parsing iCalendar data:", error);
  }
}

parseAndDisplayCalendar();

view raw JSON →