~/recurring-dates
npm install recurring-dates

Recurring dates
without the math.

One function. One config object. Daily, weekly, monthly, and yearly schedules — with ordinals, weekday pickers, custom intervals, and date exclusions.

ESM + UMDReact hookZero dependenciesValidated inputCustom FORMAT
generateRecurringDates(config)result

text

Every week on Monday and Thursday

dates

06-01-202509-01-202513-01-202516-01-202520-01-202523-01-202527-01-202530-01-2025
FREQUENCY:"W"WEEK_DAYS:["MON","THU"]INTERVAL:1

Frequencies

Four modes. One API.

input

generateRecurringDates({
  STARTS_ON: "01-01-2025",
  ENDS_ON:   "05-01-2025",
  FREQUENCY: "D",
})

output

text

Every day

dates
01-01-202502-01-202503-01-202504-01-202505-01-2025

Generates one date per day between start and end.

How It Works

Three steps to a schedule.

01

Install

One npm command. No peer dependencies beyond React (optional).

terminal
npm install recurring-dates

02

Configure

Pass a config object with your start/end dates, frequency, and any filters.

config.js
{ STARTS_ON, ENDS_ON, FREQUENCY, WEEK_DAYS }

03

Get Dates

Receive a sorted array of date strings and a human-readable description.

result.js
{ text, dates }

API

Works in Vanilla JS and React.

Import from ESM, require as CJS, or drop a <script> tag — the UMD bundle exposes window.RecurringDates.

generateRecurringDates

Core function. Returns { text, dates }.

getRecurringDates

Same, but always returns an object.

useRecurringDates

React hook with useMemo built-in.

Full API reference
index.js
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

130 tests. Zero surprises.

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.js

Daily frequency — intervals, boundaries, leap years, exclusions

weekly.test.js

Weekly frequency — single/multi weekdays, intervals, year boundaries

monthly.test.js

Monthly frequency — specific dates, ordinal weekdays, intervals

yearly.test.js

Yearly frequency — ordinals, multiple months, LAST weekday

validation.test.js

Config validation — missing fields, invalid dates, wrong order

edge-cases.test.js

Format variants — YYYY-MM-DD, MM/DD/YYYY, DD.MM.YYYY, D/M/YYYY, MMM DD YYYY

current-format.test.js

Output contract — text descriptions match expected strings

Found a bug or missing case?

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 an issue on GitHubBrowse existing issues

Ready to stop writing date loops?

Open source · MIT · Works in any JS project