Get All Dates Between Two Dates in JavaScript

To list every day between two dates, iterate a Temporal.PlainDate with .add({ days: 1 }) until you reach the end β€” calendar-day steps that never drift across DST. Part of Working with Date Ranges and Intervals.

Why this scenario is tricky

Enumerating the days between two dates by adding 24 hours in a loop drifts across a DST transition: on the spring-forward day, 24 hours lands you at 01:00 the next day instead of 00:00, and after enough iterations you skip or repeat a date. The fix is to iterate on a calendar type β€” Temporal.PlainDate β€” where .add({ days: 1 }) means the next calendar day regardless of how many real hours it contained.

Iterate calendar days, not 24-hour stepsAdding 24 hours drifts across DSTIterate calendar days, not 24-hour stepscursor += 86_400_000 msskips/repeats a day at DSTcursor.add({ days: 1 })always the next calendar dayPlainDate iteration is immune to the 23- and 25-hour days DST creates.

Minimal working solution

Loop while the cursor is before the end, collecting each PlainDate.

import { Temporal } from '@js-temporal/polyfill';
function datesBetween(start: Temporal.PlainDate, end: Temporal.PlainDate) {
  const out: Temporal.PlainDate[] = [];
  // Half-open: include start, exclude end.
  for (let d = start; Temporal.PlainDate.compare(d, end) < 0; d = d.add({ days: 1 })) out.push(d);
  return out;
}

Walk the calendarAdd one calendar day until you reach the endWalk the calendarcursor=startpush, add{days:1}stop at end

Full production version

A generator avoids allocating the whole array for long ranges, and a step parameter supports every-N-days.

import { Temporal } from '@js-temporal/polyfill';
function* eachDate(start: Temporal.PlainDate, end: Temporal.PlainDate, step = 1) {
  if (step < 1) throw new RangeError('step must be >= 1');
  for (let d = start; Temporal.PlainDate.compare(d, end) < 0; d = d.add({ days: step })) yield d;
}
// for (const d of eachDate(a, b)) render(d);

A lazy generatorYield dates on demand with an optional stepA lazy generatorstart,end,stepvalidate stepyield cursoradd step

Verification snippet

Enumeration assertionsCounts stay correct across DSTAssertions that prove the edge caseMar 07–Mar 10 20263 datesspans spring-forwardno skip/repeatstart == endemptystep 2every other day

Common pitfalls

Enumeration pitfalls24-hour steps and inclusive endsWrongRightnew Date + 24h loopDST driftPlainDate.add({days:1})calendar-correct<= end (inclusive)one extra day< end (half-open)exact count

Frequently Asked Questions

How do I list every date between two dates without DST bugs?

Iterate on Temporal.PlainDate and advance with .add({ days: 1 }). Because PlainDate has no time or zone, each step is exactly one calendar day, so a range crossing a daylight-saving boundary produces the correct list with no skipped or duplicated dates.

Should the end date be included in the list?

Follow the half-open convention and exclude it: loop while compare(cursor, end) < 0. That way a range from Monday to Thursday yields Monday, Tuesday, Wednesday, and two adjacent ranges never share a date.