How to Add Days to a Date in TypeScript (setDate and DST)

Copy the Date, then call setDate(getDate() + days) on the copy: that’s how you add days to a date in TypeScript. JavaScript rolls the month and year over for you, and negative numbers go back in time:

const due = new Date(start);
due.setDate(due.getDate() + 30);

Every result here came from TypeScript 7.0.2 and Node.js v22.22.2 in strict mode, with the time zone set to America/New_York.

In this tutorial, I’ll build a typed helper, show why adding 86,400,000 ms breaks at daylight saving time, and cover UTC and business days.

Add days to a date with setDate()

getDate() returns the day of the month. Past the month’s end, setDate() moves into the next month or year:

function addDays(date: Date, days: number): Date {
  const result = new Date(date);          // copy, so the input stays the same
  result.setDate(result.getDate() + days);
  return result;
}

const show = (d: Date) => d.toDateString();
console.log("Jan 30 + 3: ", show(addDays(new Date(2026, 0, 30), 3)));
console.log("Dec 30 + 5: ", show(addDays(new Date(2026, 11, 30), 5)));
console.log("Feb 28 + 1: ", show(addDays(new Date(2028, 1, 28), 1)));

Output:

Jan 30 + 3:  Mon Feb 02 2026
Dec 30 + 5:  Mon Jan 04 2027
Feb 28 + 1:  Tue Feb 29 2028
Command Prompt output of a TypeScript addDays helper rolling over a month end, a year end and a leap day
January rolls into February, December 2026 into January 2027, and 2028 gets its leap day.

The helper copies first because setDate() edits the object in place, a habit I also use when adding minutes to a date. For a single day, see getting tomorrow’s date in TypeScript.

Is adding 86,400,000 ms the same as adding a day?

Many snippets add days * 86400000 to the timestamp. That’s always 24 hours, but you’ll get a 23-hour local day in March and a 25-hour one in November:

const DAY_MS = 86_400_000;
const time = (d: Date) => d.toLocaleString("en-US", { dateStyle: "medium", timeStyle: "short" });

function compare(label: string, start: Date): void {
  const bySetDate = new Date(start);
  bySetDate.setDate(bySetDate.getDate() + 1);
  const byMs = new Date(start.getTime() + DAY_MS);
  const hours = (bySetDate.getTime() - start.getTime()) / 3_600_000;
  console.log(label);
  console.log("  setDate +1:   ", time(bySetDate), `(${hours} hours later)`);
  console.log("  + 86400000 ms:", time(byMs));
}

console.log("Time zone:", Intl.DateTimeFormat().resolvedOptions().timeZone);
compare("Spring forward, Mar 7 2026 11:30 PM", new Date(2026, 2, 7, 23, 30));
compare("Fall back, Nov 1 2026 12:30 AM", new Date(2026, 10, 1, 0, 30));

Output:

Time zone: America/New_York
Spring forward, Mar 7 2026 11:30 PM
  setDate +1:    Mar 8, 2026, 11:30 PM (23 hours later)
  + 86400000 ms: Mar 9, 2026, 12:30 AM
Fall back, Nov 1 2026 12:30 AM
  setDate +1:    Nov 2, 2026, 12:30 AM (25 hours later)
  + 86400000 ms: Nov 1, 2026, 11:30 PM
Command Prompt output comparing TypeScript setDate and adding 86400000 ms across the March and November 2026 DST changes in New York
setDate() keeps the clock time; the millisecond version skips to March 9 and, in November, never leaves November 1.

So use setDate() for calendar days like due dates, and milliseconds only for true durations, as in adding seconds to a date. A UTC server hides this, so test with a TZ value.

Add days to a UTC or date-only string

new Date("2026-03-08") is parsed as midnight UTC, which is still March 7 in New York. Local setDate() then crosses the DST change, so stay in UTC end to end:

const parsed = new Date("2026-03-08");          // date-only string = midnight UTC

const local = new Date(parsed);
local.setDate(local.getDate() + 1);
console.log("local setDate:", local.toISOString());

const utc = new Date(parsed);
utc.setUTCDate(utc.getUTCDate() + 1);
console.log("setUTCDate:   ", utc.toISOString().slice(0, 10));

Output:

local setDate: 2026-03-08T23:00:00.000Z
setUTCDate:    2026-03-09
Command Prompt output of TypeScript adding days with setUTCDate to a date-only ISO string
The local version ends at 23:00 UTC on March 8, a day short; setUTCDate() gives March 9.

That slice(0, 10) trick is one of several in formatting dates as YYYY-MM-DD in TypeScript. For user input, run checks for invalid dates first.

Add business days and skip weekends

Shipping dates usually skip Saturdays and Sundays, so step one day at a time and count only weekdays:

function addBusinessDays(date: Date, days: number): Date {
  const result = new Date(date);
  let added = 0;
  while (added < days) {
    result.setDate(result.getDate() + 1);
    const day = result.getDay();               // 0 = Sunday, 6 = Saturday
    if (day !== 0 && day !== 6) added++;
  }
  return result;
}

const ordered = new Date(2026, 10, 20);         // Friday, Nov 20, 2026
console.log("ordered: ", ordered.toDateString());
console.log("+5 business days:", addBusinessDays(ordered, 5).toDateString());

Output:

ordered:  Fri Nov 20 2026
+5 business days: Fri Nov 27 2026
Command Prompt output of a TypeScript addBusinessDays helper skipping a weekend
Five business days from Friday, November 20, 2026 skip the weekend and land the next Friday.

The weekend is skipped, so you get the 27th, not the 25th. To count the gap afterward, use the days between two dates. Holidays need a lookup set.

Working on more date math? Try these next:

Frequently asked questions

Why does setDate() change my original date?

It edits the object in place. Copy it with new Date(d) first, then change the copy.

Does setDate() handle the end of the month?

Yes. Day 33 of January becomes February 2, and December rolls into the next year.

How do I add weeks to a date?

Multiply first: addDays(date, weeks * 7).

How do I subtract days?

Pass a negative number: addDays(date, -14) goes back two weeks.

Should I use date-fns instead?

Its addDays() uses the same local-day logic, so you rarely need it.

Where is setDate() documented?