How to Convert a String to a Date in TypeScript

To convert a string to a date in TypeScript, pass an ISO 8601 string to new Date(), such as new Date("2026-10-08T14:30:00"). Then check the result, because a bad string gives an Invalid Date instead of an error, and a date-only string is read as UTC:

const d = new Date("2026-10-08T14:30:00");
if (Number.isNaN(d.getTime())) throw new Error("bad date");

Time zones change the answers here, so every run used TypeScript 7.0.2 with Node.js v22.22.2 with the time zone set to New York (Eastern Time).

You’ll see ISO strings with and without offsets, why a date-only string shows the previous day in the US, parsing MM/DD/YYYY safely, and how to spot an Invalid Date.

Convert an ISO string to a Date with new Date()

The ISO format is the only one every JavaScript engine must parse the same way. What you include decides the time zone:

const local = new Date("2026-10-08T14:30:00");        // no offset -> local time
const utc = new Date("2026-10-08T14:30:00Z");         // Z -> UTC
const offset = new Date("2026-10-08T14:30:00-07:00"); // Pacific daylight time

for (const [label, d] of [["local", local], ["utc", utc], ["offset", offset]] as const) {
  console.log(label.padEnd(7), d.toString().slice(0, 33), "|", d.toISOString());
}

Output:

local   Thu Oct 08 2026 14:30:00 GMT-0400 | 2026-10-08T18:30:00.000Z
utc     Thu Oct 08 2026 10:30:00 GMT-0400 | 2026-10-08T14:30:00.000Z
offset  Thu Oct 08 2026 17:30:00 GMT-0400 | 2026-10-08T21:30:00.000Z
Command Prompt output of TypeScript new Date parsing ISO strings without an offset, with Z and with a -07:00 offset
The same 2:30 PM wall time becomes three different instants: local Eastern time, UTC, and Pacific time.

No offset means local time; Z means UTC. The finer points of the format are in handling ISO date strings in TypeScript.

Why does my date string show the previous day?

A date-only string like "2026-10-08" is parsed as midnight UTC. In any US time zone that’s still the evening before, so the date looks one day early:

const due = new Date("2026-10-08");                    // date-only ISO = UTC midnight
console.log(due.toISOString());
console.log(due.toDateString(), "<- shows Oct 7 in New York");
console.log("getDate():", due.getDate());

function parseLocalDate(s: string): Date {
  const [y, m, d] = s.split("-").map(Number);
  return new Date(y, m - 1, d);                        // months are 0-based
}
const fixed = parseLocalDate("2026-10-08");
console.log(fixed.toDateString(), "getDate():", fixed.getDate());

Output:

2026-10-08T00:00:00.000Z
Wed Oct 07 2026 <- shows Oct 7 in New York
getDate(): 7
Thu Oct 08 2026 getDate(): 8
Command Prompt output of TypeScript new Date on a date-only string showing October 7 in New York, fixed by building a local Date
new Date(“2026-10-08”) prints Wed Oct 07 and getDate() 7 in New York; building it from year, month and day gives Oct 08.

Split the parts and call new Date(year, month - 1, day), which uses local time. Converting the other way, to UTC, is covered in converting dates to UTC in TypeScript.

Parse an MM/DD/YYYY string into a Date

US forms usually send MM/DD/YYYY. Engines aren’t required to support that format, and impossible dates like February 30 roll over silently. Parse it yourself and check the parts:

function parseUSDate(s: string): Date | null {
  const m = /^(\d{1,2})\/(\d{1,2})\/(\d{4})$/.exec(s.trim());
  if (!m) return null;
  const [month, day, year] = [Number(m[1]), Number(m[2]), Number(m[3])];
  const d = new Date(year, month - 1, day);
  // reject 02/30/2026 and friends: Date silently rolls them into the next month
  if (d.getFullYear() !== year || d.getMonth() !== month - 1 || d.getDate() !== day) return null;
  return d;
}

for (const s of ["10/08/2026", "7/4/2026", "02/30/2026", "13/01/2026", "2026-10-08"]) {
  const d = parseUSDate(s);
  console.log(s.padEnd(11), "->", d ? d.toDateString() : "null");
}

console.log("built-in, 02/30/2026:", new Date("02/30/2026").toDateString());

Output:

10/08/2026  -> Thu Oct 08 2026
7/4/2026    -> Sat Jul 04 2026
02/30/2026  -> null
13/01/2026  -> null
2026-10-08  -> null
built-in, 02/30/2026: Mon Mar 02 2026
Command Prompt output of a TypeScript parseUSDate function accepting 10/08/2026 and 7/4/2026 and rejecting 02/30/2026 and month 13
Valid US dates parse, 02/30/2026 and 13/01/2026 return null, and the built-in parser turns 02/30/2026 into March 2.

I use this round-trip check on every form date; it catches rollover. To show the result as text again, see formatting a date as MM/DD/YYYY in TypeScript.

Check whether a date string is valid

new Date() never throws. A string it can’t read gives a Date whose time is NaN, so test getTime():

function isValidDate(d: Date): boolean {
  return !Number.isNaN(d.getTime());
}

for (const s of ["2026-10-08", "2026-13-45", "October 8, 2026", "next Friday", ""]) {
  const d = new Date(s);
  console.log(JSON.stringify(s).padEnd(18), isValidDate(d) ? d.toDateString() : "Invalid Date");
}

console.log("Date.parse:", Date.parse("2026-10-08T14:30:00Z"), typeof Date.parse("x"), Date.parse("x"));

Output:

"2026-10-08"       Wed Oct 07 2026
"2026-13-45"       Invalid Date
"October 8, 2026"  Thu Oct 08 2026
"next Friday"      Invalid Date
""                 Invalid Date
Date.parse: 1791469800000 number NaN
Command Prompt output of TypeScript checking date strings for Invalid Date with getTime and NaN, plus Date.parse results
The ISO date and October 8, 2026 parse, while 2026-13-45, next Friday and the empty string are Invalid Date; Date.parse returns a number or NaN.

Notice that 2026-10-08 shows Wed Oct 07 again: the same UTC trap as above. That’s why I never trust a date-only string straight from new Date().

Node accepts "October 8, 2026", but that format isn’t guaranteed everywhere. More validation patterns are in checking for invalid dates in TypeScript.

String to date methods compared

InputUseWatch out for
2026-10-08T14:30:00new Date(s)Local time; add Z or an offset for UTC
2026-10-08new Date(y, m - 1, d)new Date(s) gives UTC midnight
10/08/2026Regex + new Date(y, m - 1, d)Rollover; engine differences
Anything from usersNumber.isNaN(d.getTime())new Date() doesn’t throw
Need a timestampDate.parse(s)Returns NaN, not an error

Once you have a Date, date math such as calculating days between dates is straightforward.

For everyday date work in TypeScript, keep these handy:

Frequently asked questions

How do I convert a string to a Date in TypeScript?

Use new Date(isoString) and check Number.isNaN(d.getTime()) to catch invalid input.

Why is my date one day off?

A date-only ISO string is parsed as UTC midnight, which is the previous evening in US time zones. Build it with new Date(y, m - 1, d).

How do I parse MM/DD/YYYY in TypeScript?

Match it with a regex, then call new Date(year, month - 1, day) and confirm the parts didn’t roll over.

How do I check if a date string is valid?

Create the Date and test !Number.isNaN(d.getTime()); also check rollover for user-entered dates.

What’s the difference between new Date() and Date.parse()?

new Date() returns a Date object; Date.parse() returns milliseconds since 1970, or NaN.

Where is the Date string format documented?