
Product
Introducing Reports: An Extensible Reporting Framework for Socket Data
Explore exportable charts for vulnerabilities, dependencies, and usage with Reports, Socket’s new extensible reporting framework.
simple-rrule
Advanced tools
A simple and high-performance TypeScript library for working with recurrence rules (RRule).
A simple implementation of the RRule standard iCalendar RFC 5545. Note that this is not a complete implementation of all standard rules, it allows parsing and expanding recurrence rules. Ideal for getting the complete set of recurring events in a calendar, the simple-rrule library aims to simplify this process.
Important: Does not work with TZ timezone.
Example:
import { expandRRule,rRuleDefaultValues } from 'simple-rrule'
const rRule: IRrule = {
...rRuleDefaultValues,//default values
dtStart: '2023-01-01T10:00:00.000Z', //start of year 2023
dtEnd: '2023-01-01T11:00:00.000Z',//duration of 1 hour
frequency: 'HOURLY',
interval: 10 // every 10 hours
}
//returns the rRuleString
const rRuleString = getRRuleString(rRule)
console.log(rRuleString)
// DTSTART:20230101T100000Z
// DTEND:20230101T110000Z
// RRULE:FREQ=HOURLY;INTERVAL=10;WKST=SU
//returns the rRule object
const parseR = parseRecurrenceFromString(rRuleString)
const result1 = expandRRule(
rRule,
new Date('2023-12-31'),
new Date('2024-01-01')//year transition
)
console.log('result1', result1)
// result {
// r: {
// dtStart: 2023-01-01T10:00:00.000Z,
// dtEnd: 2023-01-01T11:00:00.000Z,
// frequency: 'HOURLY',
// interval: 10,
// count: 0,
// byDay: '',
// byMonth: 0,
// byMonthDay: 0,
// bySetPos: 0,
// wkst: 'SU',
// startRangePeriod: 2023-12-31T00:00:00.000Z,
// endRangePeriodOrUntil: 2024-01-01T00:00:00.000Z,
// secondsDuration: 3600,
// hasErrors: false,
// errorMessages: '',
// eventsCount: 0,
// startIndexCount: 37,
// firstEventInRangePeriod: 2023-01-16T20:00:00.000Z
// },
// events: [
// { date: 2023-12-31T04:00:00.000Z, index: 874 },
// { date: 2023-12-31T14:00:00.000Z, index: 875 },
// { date: 2024-01-01T00:00:00.000Z, index: 876 }
// ]
// }
const result2 = expandRRule(
rRule,
new Date('2024-02-28'),
new Date('2024-03-01') //leap year
)
console.log(result2)
// result2 {
// r: {
// dtStart: 2023-01-01T10:00:00.000Z,
// dtEnd: 2023-01-01T11:00:00.000Z,
// frequency: 'HOURLY',
// interval: 10,
// count: 0,
// byDay: '',
// byMonth: 0,
// byMonthDay: 0,
// bySetPos: 0,
// wkst: 'SU',
// startRangePeriod: 2024-02-28T00:00:00.000Z,
// endRangePeriodOrUntil: 2024-03-01T00:00:00.000Z,
// secondsDuration: 3600,
// hasErrors: false,
// errorMessages: '',
// eventsCount: 0,
// startIndexCount: 43,
// firstEventInRangePeriod: 2023-01-19T08:00:00.000Z
// },
// events: [
// { date: 2024-02-28T08:00:00.000Z, index: 1016 },
// { date: 2024-02-28T18:00:00.000Z, index: 1017 },
// { date: 2024-02-29T04:00:00.000Z, index: 1018 },
// { date: 2024-02-29T14:00:00.000Z, index: 1019 },
// { date: 2024-03-01T00:00:00.000Z, index: 1020 }
// ]
// }
expandRRule is focused on performance, it doesn't build event loops from the beginning. To optimize performance it makes calculations and returns events within the specified period, the index in events is the event counter.
The library uses Zod4 for automatic validation in main functions:
// Invalid values generate clear errors
const rRule = parseRecurrenceFromString(`
DTSTART:20231201T100000Z
RRULE:FREQ=WEEKLY;INTERVAL=0 // ❌ Interval must be >= 1
`)
// Returns undefined and logs validation error
type IRrule = {
dtStart: string; //iso datetime
dtEnd: string; //iso datetime
frequency: Frequency;
interval: number;
count: number;
byDay: string;
byMonth: number;
byMonthDay: number;
bySetPos: number;
wkst: Weekday;
until?: string | undefined; //iso datetime
}
This library has extensive test coverage, but needs help with documentation.
expandRRule and expandRRuleFromString for rule expansiongetRRuleString for RRule string generationparseRecurrenceFromString for RRule string parsingparseWeekDay for weekday conversionvalidateRrule for rule validationaddDays, addHours, addMinutes, addMonths, addYears, addWeeks, addSeconds, addMilliseconds, differenceInDays, differenceInHours, differenceInMinutes, differenceInMonths, differenceInSeconds, differenceInWeeks, differenceInYears, differenceInMilliseconds, eachDateOfInterval, getStartOfWeekWithoutChangeTime, getWeekDayFromDate, getWeekDayName, isBefore, isLastDayOfMonth, compareAsc, setByDay, setByMonth, toRRuleDateString, fromRruleDateStringToDate, isDate, isWeekDayValid, isBySetPosValid, getBySetPos, eachMonthOfIntervalWithTime, eachYearOfIntervalWithTime
rRuleFields, interfaces IDateEvents, IExpandResult, IRrule, IRuleExtended, IWeekDayInfo and types Frequency, Weekday, Day, Month, BySetPos, YearMonths, MonthDays.# With npm
npm install simple-rrule
# With yarn
yarn add simple-rrule
# With pnpm
pnpm add simple-rrule
FAQs
simple rrule string parser and expand date events
The npm package simple-rrule receives a total of 34 weekly downloads. As such, simple-rrule popularity was classified as not popular.
We found that simple-rrule demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
Explore exportable charts for vulnerabilities, dependencies, and usage with Reports, Socket’s new extensible reporting framework.

Product
Socket for Jira lets teams turn alerts into Jira tickets with manual creation, automated ticketing rules, and two-way sync.

Company News
Socket won two 2026 Reppy Awards from RepVue, ranking in the top 5% of all sales orgs. AE Alexandra Lister shares what it's like to grow a sales career here.