One function. One config object. Daily, weekly, monthly, and yearly schedules — with ordinals, weekday pickers, custom intervals, and date exclusions.
text
“Every week on Monday and Thursday”
dates
Frequencies
input
generateRecurringDates({
STARTS_ON: "01-01-2025",
ENDS_ON: "05-01-2025",
FREQUENCY: "D",
})output
“Every day”
Generates one date per day between start and end.
How It Works
01
One npm command. No peer dependencies beyond React (optional).
npm install recurring-dates02
Pass a config object with your start/end dates, frequency, and any filters.
{ STARTS_ON, ENDS_ON, FREQUENCY, WEEK_DAYS }03
Receive a sorted array of date strings and a human-readable description.
{ text, dates }API
Import from ESM, require as CJS, or drop a <script> tag — the UMD bundle exposes window.RecurringDates.
generateRecurringDatesCore function. Returns { text, dates }.
getRecurringDatesSame, but always returns an object.
useRecurringDatesReact hook with useMemo built-in.
import { generateRecurringDates } from "recurring-dates";
const { text, dates } = generateRecurringDates({
STARTS_ON: "01-01-2025",
ENDS_ON: "31-01-2025",
FREQUENCY: "W",
WEEK_DAYS: ["MON", "THU"],
EXCLUDE_DATES: ["13-01-2025"],
});Reliability
Every frequency mode, interval, ordinal combination, edge case, and format variant is verified by an automated test suite that runs on every change.
130
Total tests
7
Test suites
100%
Pass rate
0
Dependencies
daily.test.jsDaily frequency — intervals, boundaries, leap years, exclusions
weekly.test.jsWeekly frequency — single/multi weekdays, intervals, year boundaries
monthly.test.jsMonthly frequency — specific dates, ordinal weekdays, intervals
yearly.test.jsYearly frequency — ordinals, multiple months, LAST weekday
validation.test.jsConfig validation — missing fields, invalid dates, wrong order
edge-cases.test.jsFormat variants — YYYY-MM-DD, MM/DD/YYYY, DD.MM.YYYY, D/M/YYYY, MMM DD YYYY
current-format.test.jsOutput contract — text descriptions match expected strings
The test suite covers every documented pattern, but edge cases in the wild are endless. If you hit an unexpected result — wrong dates, a format that doesn't parse, an ordinal that misfires — please open a GitHub issue.
A good issue includes the config object you passed, the output you received, and the output you expected. That's all it takes to get a fix in fast.
// minimal repro
generateRecurringDates({
STARTS_ON: "...",
ENDS_ON: "...",
FREQUENCY: "W",
// expected: [...]
});
Open source · MIT · Works in any JS project