ical-generator is a small but fine library with which you can very easily create a valid iCal calendars, for example
to generate subscriptionable calendar feeds.
npm install ical-generator
import ical, { ICalCalendarMethod } from 'ical-generator';
import http from 'node:http';
const calendar = ical({ name: 'my first iCal' });
// A method is required for outlook to display event as an invitation
calendar.method(ICalCalendarMethod.REQUEST);
const startTime = new Date();
const endTime = new Date();
endTime.setHours(startTime.getHours() + 1);
calendar.createEvent({
start: startTime,
end: endTime,
summary: 'Example Event',
description: 'It works ;)',
location: 'my room',
url: 'http://sebbo.net/',
});
http.createServer((req, res) => {
res.writeHead(200, {
'Content-Type': 'text/calendar; charset=utf-8',
'Content-Disposition': 'attachment; filename="calendar.ics"',
});
res.end(calendar.toString());
}).listen(3000, '127.0.0.1', () => {
console.log('Server running at http://127.0.0.1:3000/');
});See the examples folder for more examples.
ical-generator supports native Date,
Day.js, Luxon's DateTime,
the older moment.js, moment-timezone,
TZDate and Temporal objects.
You can also pass a string which is then passed to javascript's Date internally.
It is recommended to use UTC time as far as possible. ical-generator will output all time information as UTC time as
long as no time zone is defined. For day.js, a plugin is necessary for this, which is a prerequisite. If a time zone is
set, ical-generator assumes that the given time matches the time zone.
Please note that a native Date (or a string) has no time zone of its own. If a time zone is set, ical-generator
uses the local time of the machine it runs on (getHours() etc.) and labels it with the given time zone. The result
therefore depends on the server's time zone: new Date('2026-07-01T09:30:00Z') with timezone: 'Europe/Prague' becomes
DTSTART;TZID=Europe/Prague:20260701T093000 on a server running in UTC, although 09:30 UTC is 11:30 in Prague. To get
the same output everywhere, pass a TZDate, a Luxon DateTime, a moment-timezone or a Temporal object, or do not
set a time zone so that the time is written as UTC.
If a time zone is used, it is also recommended to use a VTimezone generator. Such a function generates a VTimezone entry
and returns it. For example, timezones-ical-library or @touch4it/ical-timezones can be used for this:
import { ICalCalendar } from 'ical-generator';
import { getVtimezoneComponent } from '@touch4it/ical-timezones';
import { TZDate } from '@date-fns/tz';
const cal = new ICalCalendar();
cal.timezone({
name: 'Europe/London',
generator: getVtimezoneComponent,
});
cal.createEvent({
start: new TZDate(2026, 0, 15, 9, 30, 'Europe/London'), // 09:30 London time
timezone: 'Europe/London',
});import { ICalCalendar } from 'ical-generator';
import { tzlib_get_ical_block } from 'timezones-ical-library';
import { TZDate } from '@date-fns/tz';
const cal = new ICalCalendar();
cal.timezone({
name: 'Europe/London',
generator: (tz) => tzlib_get_ical_block(tz)[0],
});
cal.createEvent({
start: new TZDate(2026, 0, 15, 9, 30, 'Europe/London'), // 09:30 London time
timezone: 'Europe/London',
});If a moment-timezone object or Luxon's setZone method works, ical-generator sets it according to the time zone set
in the calendar/event.
npm test
npm run coverage
It's here. If you need the changelog for
ical-generator 1.x.x and older, you'll find it here.
Copyright (c) Sebastian Pekarek under the MIT license.