@rrulenet/rrule
v0.1.3
Published
Classic rrule.js-style recurrence API, backed by a maintained engine built for production scheduling.
Maintainers
Readme
@rrulenet/rrule provides the classic rrule.js-style API in the ecosystem. It is designed for compatibility-focused applications that want familiar classes, stable recurrence behavior, timezone-aware queries, set composition, and text rendering.
Use @rrulenet/rrule when you want the familiar class-based compat surface. Use @rrulenet/recurrence when your application boundary is already built around the Temporal API and a single Recurrence type.
Table of Contents
Install
npm install @rrulenet/rruleWhy RRule
@rrulenet/rrule exists for applications that want the classic recurrence model:
RRulefor one ruleRRuleSetfor composed include/exclude schedulesrrulestr()for parsing and round-tripping RFC-style stringsDatevalues at the API boundary
That makes it a good fit for:
- migrations from
rrule.js - existing codebases built around
Date - applications that want a familiar class-based API without moving their boundary to
Temporal
See also:
API
import {
RRule,
RRuleSet,
SetAlgebra,
rrulestr,
Frequency,
Weekday,
ALL_WEEKDAYS,
datetime,
getToTextLocale,
listToTextLocales,
registerToTextLocale,
} from '@rrulenet/rrule';Main exports:
RRuleRRuleSetSetAlgebrarrulestrFrequencyWeekdayALL_WEEKDAYSdatetimegetToTextLocalelistToTextLocalesregisterToTextLocale
Recommended usage:
- choose
@rrulenet/rrulewhen you want the familiar class-based compat surface - choose
@rrulenet/recurrencewhen your app boundary is built around the Temporal API - avoid importing from
@rrulenet/coredirectly in application code
Getting Started
import { RRule, Frequency, datetime } from '@rrulenet/rrule';
const rule = new RRule({
freq: Frequency.WEEKLY,
count: 4,
byweekday: [RRule.MO, RRule.WE],
dtstart: datetime(2026, 4, 13, 9, 0, 0),
});
console.log(rule.all().map((value) => value.toISOString()));
// [
// '2026-04-13T09:00:00.000Z',
// '2026-04-15T09:00:00.000Z',
// '2026-04-20T09:00:00.000Z',
// '2026-04-22T09:00:00.000Z'
// ]Examples
RRule
import { RRule, Frequency, datetime } from '@rrulenet/rrule';
const rule = new RRule({
freq: Frequency.MONTHLY,
bymonthday: [1, 15],
count: 4,
dtstart: datetime(2026, 1, 1, 9, 0, 0),
});
console.log(rule.toString());
// DTSTART:20260101T090000Z
// RRULE:FREQ=MONTHLY;COUNT=4;BYMONTHDAY=1,15
console.log(rule.toText());
// every month on the 1st and 15th day of the month at 9 AM UTC for 4 timesRRuleSet
import { RRule, RRuleSet, Frequency, datetime } from '@rrulenet/rrule';
const set = new RRuleSet();
set.tzid('UTC');
set.rrule(new RRule({
freq: Frequency.DAILY,
count: 4,
dtstart: datetime(2026, 4, 11, 9, 0, 0),
}));
set.exdate(new Date('2026-04-12T09:00:00.000Z'));
set.rdate(new Date('2026-04-20T09:00:00.000Z'));
console.log(set.all().map((value) => value.toISOString()));
// [
// '2026-04-11T09:00:00.000Z',
// '2026-04-13T09:00:00.000Z',
// '2026-04-14T09:00:00.000Z',
// '2026-04-20T09:00:00.000Z'
// ]
console.log(set.toString());
// DTSTART:20260411T090000Z
// RRULE:FREQ=DAILY;COUNT=4
// RDATE:20260420T090000Z
// EXDATE:20260412T090000ZSetAlgebra
import { RRule, SetAlgebra, Frequency, datetime } from '@rrulenet/rrule';
const expression = SetAlgebra.union(
new RRule({
freq: Frequency.WEEKLY,
count: 3,
byweekday: [RRule.MO],
dtstart: datetime(2026, 4, 13, 9, 0, 0),
}),
new RRule({
freq: Frequency.WEEKLY,
count: 3,
byweekday: [RRule.WE],
dtstart: datetime(2026, 4, 15, 9, 0, 0),
}),
);
console.log(expression.all().map((value) => value.toISOString()));
// [
// '2026-04-13T09:00:00.000Z',
// '2026-04-15T09:00:00.000Z',
// '2026-04-20T09:00:00.000Z',
// '2026-04-22T09:00:00.000Z',
// '2026-04-27T09:00:00.000Z',
// '2026-04-29T09:00:00.000Z'
// ]rrulestr()
import { RRuleSet, rrulestr } from '@rrulenet/rrule';
const parsed = rrulestr([
'DTSTART;TZID=UTC:20260411T090000',
'RRULE:FREQ=DAILY;COUNT=2',
'RDATE:20260415T090000Z',
'EXDATE:20260412T090000Z',
].join('\n'));
console.log(parsed instanceof RRuleSet);
// true
console.log(parsed.toString());
// DTSTART:20260411T090000Z
// RRULE:FREQ=DAILY;COUNT=2
// RDATE:20260415T090000Z
// EXDATE:20260412T090000ZNotes
RSCALEandSKIPare part of the compat rule model.toText()and locale registry helpers are available here.- The same engine also powers the Temporal-first API exposed by
@rrulenet/recurrence.
Development
npm install
npm test