rrule

A JavaScript/TypeScript library for computing iCalendar (RFC 5545) recurrence rules for calendar dates.

Library
npm
v2.8.1
3,744 stars
BSD 3-Clause License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
50 /100 Fair
Development Activity 0
Maintenance 20
Community 80
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
65 /100 Good
Architecture 78
Code Quality 82
Innovation 55
Learning Curve 45

rrule is a JavaScript/TypeScript port of Python’s python-dateutil recurrence engine, implementing the iCalendar RFC 5545 RRULE specification for computing recurring calendar dates. It exposes an RRule class for single recurrence rules, an RRuleSet class for combining multiple rules with explicit inclusion/exclusion dates, and an rrulestr parser that turns an iCalendar RRULE string directly into a usable rule object.

Beyond RFC compliance, the library adds natural-language conversion in both directions: toText()/fromText() translate a rule like “every 5 weeks on Monday, Friday until January 31, 2013” into RRule options and back, which is useful for building human-facing recurrence pickers without hand-rolling the parsing logic. It ships as pure TypeScript with a single runtime dependency (tslib), targeting both browser and Node environments, and is widely used as the recurrence engine behind calendar and scheduling UIs.

What You Get

  • An RRule class covering the full RFC 5545 option set (freq, interval, count, until, byweekday, bymonth, bymonthday, byyearday, byweekno, bysetpos, byhour/minute/second, byeaster)
  • An RRuleSet class for composing multiple RRULEs plus explicit RDATE/EXDATE inclusion and exclusion dates into one combined occurrence set
  • An rrulestr() parser that converts an iCalendar RRULE/RRuleSet string directly into a working rule object, and toString()/optionsToString() for the reverse
  • Natural-language conversion via toText()/fromText() and parseText(), translating rules to and from human-readable phrases like “every 5 weeks on Monday, Friday until January 31, 2013”
  • IANA timezone support via the Intl API through the tzid option, plus a datetime() helper for constructing dates in the library’s expected UTC-based format
  • Built-in occurrence caching so repeated all()/between() calls on the same rule don’t re-run the iteration algorithm

Common Use Cases

  • Powering recurrence pickers in calendar and scheduling UIs, where a user picks “every 2 weeks on Tue/Thu” and the app needs the resulting occurrence dates
  • Parsing and re-serializing iCalendar RRULE strings when importing/exporting .ics calendar data
  • Computing the next N occurrences of a recurring task, billing cycle, or reminder for background job scheduling
  • Converting recurrence rules to and from human-readable text for calendar UIs that display rules in plain language

Under The Hood

Architecture Execution flows from the public RRule class (src/rrule.ts), which parses and normalizes constructor options via parseOptions/initializeOptions (src/parseoptions.ts) into a ParsedOptions object, then delegates all query methods (all, between, before, after) to a shared _iter call into the standalone iter() function (src/iter/index.ts). That iterator walks calendar periods year-by-month using an Iterinfo helper (src/iterinfo/index.ts, with easter/month/year-specific submodules) to build day masks and time sets, filtering days against every by* constraint before emitting accepted dates through an IterResult/CallbackIterResult accumulator (src/iterresult.ts, src/callbackiterresult.ts). RRuleSet (src/rruleset.ts) layers on top by merging multiple RRule/EXRULE instances with explicit RDATE/EXDATE arrays and de-duplicating the combined output, while rrulestr/parsestring/optionsToString (src/rrulestr.ts, src/parsestring.ts, src/optionstostring.ts) handle iCalendar string round-tripping and a separate src/nlp/ module handles natural-language conversion — a clean layered separation between option parsing, core iteration, set composition, string serialization, and natural-language translation, with a Cache class (src/cache.ts) memoizing repeated queries per rule instance. The core abstraction to protect is the day/time-mask iteration in iter() and Iterinfo; changing it touches every query method and both serialization paths at once.

Tech Stack The library is authored entirely in TypeScript (98%+ of source bytes) with a single runtime dependency, tslib, keeping the published bundle dependency-free for consumers. The build pipeline compiles with tsc against tsconfig.build.json and bundles with Webpack 5 (webpack.config.js) plus terser-webpack-plugin for minification, publishing both an ES5 CommonJS build (dist/es5) and an ESM build (dist/esm) with generated .d.ts types. Linting runs through ESLint 8 with @typescript-eslint and eslint-plugin-jsdoc/eslint-plugin-import, formatting through Prettier 2, both wired into husky + lint-staged pre-commit hooks. There is no database or network layer — the library is pure computation over JS Date objects, with the Intl API used for IANA timezone resolution (tzid option) rather than a timezone library dependency.

Code Quality Testing uses Jest with ts-jest (jest.config.js) plus mockdate for deterministic date-based assertions, and the test/ directory mirrors the src/ module layout with a dedicated test file per module (rrule, rruleset, rrulestr, parseoptions, parsestring, cache, datetime, helpers, nlp) plus shared fixtures in test/lib. CI (.github/workflows/nodejs.yml) runs the full suite across three Node versions and, notably, across five different LANG/TZ combinations (including Pacific/Kiritimati and Africa/Nairobi) specifically to catch timezone- and locale-sensitive date bugs, then reports coverage to Codecov via nyc. Source files carry substantial inline JSDoc-style comments on public methods (parameter/return documentation on every RRule query method), and the constructor/option-parsing path validates inputs and throws explicit Errors (e.g. RRule.between/before/after reject invalid Date arguments) rather than silently returning bad data.

API Design The public surface is intentionally small and RFC-mirroring: a single RRule constructor takes an options object whose keys map directly to iCalendar RRULE parameters (freq, interval, byweekday, etc.), so anyone already familiar with the RFC or with Python’s dateutil.rrule (which this library is explicitly ported from) can use it with minimal ramp-up. Constants like RRule.MO/RRule.WEEKLY avoid magic numbers, and the datetime() helper sidesteps a documented JavaScript Date/timezone footgun that the README calls out at length. The main friction point for newcomers is exactly that UTC-handling caveat — the README devotes a long, explicit section to it because getting it wrong silently produces off-by-hours results — and the natural-language toText()/fromText() conversion is explicitly approximate rather than complete, which the library documents rather than hides.

Used by 11 apps in this directory

TypeScript
96%
Other

Cal.diy

Scheduling

48,697

The 100% MIT-licensed, community-driven scheduling platform — self-host your own booking infrastructure with no enterprise strings attached.

View details
91
Repo Health
86
Technical
65
Dependency
Built with
TypeScript 96%
Updated 6 days ago
Ruby
61%
GPL 2.0

Discourse

Community

47,915

Open-source community platform with dynamic trust levels, real-time chat, and a powerful plugin architecture for self-hosted forums.

View details
89
Repo Health
89
Technical
67
Dependency
Built with
Ruby 61%
JavaScript 32%
Updated 4 days ago
TypeScript
50%

Kener

Devops · Monitoring

5,181

Stunning, self-hosted status pages with real-time uptime monitoring, incident management, and multi-channel notifications in a single Docker container.

View details
86
Repo Health
76
Technical
67
Dependency
Built with
TypeScript 50%
Svelte 47%
Updated 2 weeks ago
TypeScript
99%
AGPL 3.0

Manage

Collaboration · Project Management

71

Self-hosted, open-source project management with tasks, calendars, docs, and real-time team collaboration.

View details
39
Repo Health
57
Technical
71
Dependency
Built with
TypeScript 99%
Updated 1 months ago
TypeScript
92%
Other

n8n

Automation · No Code Platforms

206,147

Code when you need it, UI when you don't — the workflow automation platform built for technical teams who refuse to choose.

View details
95
Repo Health
87
Technical
65
Dependency
Built with
TypeScript 92%
Updated 4 days ago
TypeScript
98%
Other

Novu

Developer Tools

40,084

Open-source communication infrastructure that connects your products and AI agents to every channel your users live on — Inbox, Email, SMS, Push, Chat, and more.

View details
93
Repo Health
80
Technical
64
Dependency
Built with
TypeScript 98%
Updated 5 days ago
Python
55%
Other

PostHog

Ab Testing Experimentation · Analytics · Developer Tools

39,975

The all-in-one open source product platform combining analytics, session replay, feature flags, error tracking, AI observability, and a built-in data warehouse in a single self-hostable stack.

View details
92
Repo Health
80
Technical
65
Dependency
Built with
Python 55%
TypeScript 36%
Updated 4 days ago
TypeScript
50%
Other

SigNoz

Analytics · Monitoring

32,224

Self-host your entire observability stack — logs, metrics, traces, and LLM monitoring — in one OpenTelemetry-native platform, without the Datadog bill.

View details
92
Repo Health
83
Technical
67
Dependency
Built with
TypeScript 50%
Go 38%
Updated 4 days ago
TypeScript
85%
Apache 2.0

superset

AI Code Assistants · AI Development

14,690

Orchestrate an army of AI coding agents—Claude Code, Codex, Gemini CLI, and more—running simultaneously in isolated git worktrees from a single Electron desktop app.

View details
86
Repo Health
80
Technical
64
Dependency
Built with
TypeScript 85%
Updated 4 days ago

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers