Small TypeScript library for generating calendar-friendly date ranges: days, weeks, exact months and months extended to full weeks.
The library is intentionally narrow. It is useful as a foundation for simple calendar views, worklists, dashboards and date grouping. It is not a booking engine, recurrence engine or full scheduler.
npm install easy-date-range luxonluxon is a peer dependency. easy-date-range accepts JavaScript Date
objects and Luxon DateTime objects as inputs, and returns Luxon DateTime
objects by default.
import { DateRange, WEEKDAY } from "easy-date-range";
const week = new DateRange().getWeek({
refDate: new Date("2026-05-14"),
refWeekday: WEEKDAY.Monday,
});
week.dateTimes.forEach((dateTime) => {
console.log(dateTime.toISODate());
});Use toDates() when JavaScript Date objects are needed:
const jsDates = week.toDates();The root package exports:
import {
DateRange,
RANGE_TYPE,
WEEKDAY,
chunkMonthExtended,
type OptionsDays,
type OptionsMonthExact,
type OptionsMonthExtended,
type OptionsWeek,
} from "easy-date-range";Create an instance and initialize it with one range generator:
new DateRange().getDays(options);
new DateRange().getWeek(options);
new DateRange().getMonthExact(options);
new DateRange().getMonthExtended(options);
new DateRange().getNext(dateRange);
new DateRange().getPrevious(dateRange);After initialization, the instance exposes:
dateRange.dateTimes; // readonly DateTime[]
dateRange.toDateTimes(); // readonly DateTime[]
dateRange.toDates(); // Date[]
dateRange.refDate;
dateRange.refWeekday;
dateRange.startOffset;
dateRange.endOffset;
dateRange.daysCount;
dateRange.rangeType;
dateRange.isNext;
dateRange.isPrevious;dateTimes and toDateTimes() return readonly copies. Mutating the returned
array does not mutate the DateRange instance.
All range generators accept an optional object. Passing {} is valid and uses
defaults. Unknown option properties throw a runtime error, which helps catch
misspellings in JavaScript code.
Common options:
| Option | Type | Default | Description |
|---|---|---|---|
refDate |
DateTime | Date |
current date/time | Reference date used to calculate the range. |
startOffset |
number |
0 |
Integer offset applied to the beginning of the range. |
endOffset |
number |
0 |
Integer offset applied to the end of the range. |
Method-specific options:
| Method | Option | Type | Default |
|---|---|---|---|
getDays |
daysCount |
positive integer | 1 |
getWeek |
refWeekday |
WEEKDAY / 1..7 |
WEEKDAY.Monday |
getMonthExtended |
refWeekday |
WEEKDAY / 1..7 |
WEEKDAY.Monday |
Offsets are integer day adjustments applied after the base range is generated.
- Positive
startOffsetadds dates before the range. - Negative
startOffsetremoves dates from the beginning. - Positive
endOffsetadds dates after the range. - Negative
endOffsetremoves dates from the end.
Negative offsets cannot remove the whole range.
const range = new DateRange().getMonthExact({
refDate: new Date("2026-05-14"),
startOffset: 2,
endOffset: -2,
});const currentWeek = new DateRange().getWeek();const sundayFirst = new DateRange().getWeek({
refWeekday: WEEKDAY.Sunday,
});const may = new DateRange().getMonthExact({
refDate: new Date("2026-05-14"),
});Use getMonthExtended() for calendar grids that need complete weeks.
const monthGridRange = new DateRange().getMonthExtended({
refDate: new Date("2026-05-14"),
refWeekday: WEEKDAY.Monday,
});chunkMonthExtended() splits a month-extended range into week rows.
const range = new DateRange().getMonthExtended({
refDate: new Date("2026-05-14"),
});
const weeks = chunkMonthExtended(range);Set nullNextPrevDates to replace dates outside the reference month with
null.
const weeks = chunkMonthExtended(range, {
nullNextPrevDates: true,
});const current = new DateRange().getWeek({
refDate: new Date("2026-05-14"),
});
const previous = new DateRange().getPrevious(current);
const next = new DateRange().getNext(current);Use ranges to group tasks, reviews or deadlines into simple operational buckets.
import { DateTime } from "luxon";
const tasks = [
{ title: "Review procedure", dueDate: DateTime.fromISO("2026-05-14") },
{ title: "Approve record", dueDate: DateTime.fromISO("2026-05-20") },
];
const thisWeek = new DateRange().getWeek({
refDate: DateTime.now(),
});
const thisWeekMillis = new Set(
thisWeek.dateTimes.map((dateTime) => dateTime.toMillis()),
);
const dueThisWeek = tasks.filter((task) =>
thisWeekMillis.has(task.dueDate.startOf("day").toMillis()),
);easy-date-range does not provide:
- recurrence rules;
- event storage;
- booking or reservation conflict detection;
- resource availability;
- drag-and-drop scheduler UI;
- timezone policy beyond Luxon
DateTimebehavior.
For full scheduling and resource planning, use a dedicated calendar/scheduler
library and treat easy-date-range as a small helper for date projections.
easy-date-range@2.0.0 contains intentional breaking changes:
dateTimesandtoDateTimes()return readonly array copies.- Unknown properties in range generator options now throw runtime errors.
- Empty
{}options are valid and use defaults. getDays({ daysCount: 0 })is invalid;daysCountmust be at least1.@types/luxonis installed as a package dependency so generated declaration files can reference Luxon types correctly.
npm run test:run
npm run coverage
npm run lint
npm run build
npm run smoke:packsmoke:pack builds the package, checks the dry-run npm package contents and
verifies both ESM and CJS runtime imports.