Question

Validate Date Instances in JavaScript: Detect Invalid Dates

Question

How can I distinguish a valid JavaScript Date instance from an invalid one?

const d = new Date("foo");

console.log(d.toString());    // "Invalid Date"
console.log(typeof d);        // "object"
console.log(d instanceof Date); // true

I want an isValidDate function that accepts a Date instance and determines whether it represents a valid date and time, rather than only validating the original date string.

Short Answer

You will learn why an invalid date is still a Date object, how JavaScript represents invalid dates internally, and how to write reliable validation functions using getTime() and Number.isNaN().

Concept

A JavaScript Date object stores one value: a timestamp measured in milliseconds from January 1, 1970 UTC. A valid date has a finite numeric timestamp.

When construction or parsing fails, JavaScript still creates a Date object, but its internal time value is NaN (Not-a-Number). That is why all of these can be true at once:

const d = new Date("foo");

console.log(d instanceof Date); // true
console.log(typeof d);          // "object"
console.log(d.getTime());       // NaN
console.log(d.toString());      // "Invalid Date"

Therefore, validating a Date instance requires two checks:

  1. Confirm the value is a date object.
  2. Confirm its timestamp is not NaN.

This matters because invalid dates can silently travel through an application and only fail later—for example, when formatting a date, saving it to an API, or calling toISOString().

Mental Model

Think of a Date as a labelled container containing a timestamp.

  • A valid Date container holds a number, such as 1714521600000.
  • An invalid Date container still exists and still has the Date label, but it holds NaN instead of a usable timestamp.

Checking value instanceof Date verifies the label. Checking value.getTime() verifies that the container holds a real timestamp.

Take Quiz

Syntax and Examples

Use getTime() to read the timestamp and Number.isNaN() to test whether it is invalid.

function isValidDate(value) {
  return value instanceof Date && !Number.isNaN(value.getTime());
}

console.log(isValidDate(new Date("2024-05-01"))); // true
console.log(isValidDate(new Date("not a date"))); // false
console.log(isValidDate("2024-05-01"));           // false
console.log(isValidDate({}));                       // false

getTime() returns:

  • A number for valid dates.
  • NaN for invalid dates.

Number.isNaN() is preferred because it only returns true for the actual numeric NaN value; it does not convert other values before testing them.

Step by Step Execution

Consider this example:

const input = "not a date";
const date = new Date(input);

const isDateObject = date instanceof Date;
const timestamp = date.getTime();
const valid = isDateObject && !Number.isNaN(timestamp);

console.log(valid); // false

Step by step:

  1. new Date(input) creates a Date object even though the text cannot be parsed.
  2. date instanceof Date is true because it is structurally a Date instance.
  3. date.getTime() returns NaN because the date has no valid timestamp.
  4. Number.isNaN(timestamp) is true.
  5. The ! operator changes that to false, so valid is false.

For a valid input such as "2024-05-01", getTime() returns a number and valid becomes true.

Real World Use Cases

  • API boundaries: Reject invalid Date values before serializing request data.
  • Form handling: Validate a date produced by a date picker or conversion function before saving it.
  • Database writes: Prevent invalid timestamps from being stored in records.
  • Scheduling: Ensure an event, reminder, or job has a usable execution time.
  • Data imports: Detect malformed dates while processing CSV files or external service responses.

For example, validate before converting to ISO format:

function serializeDate(date) {
  if (!isValidDate(date)) {
    throw new TypeError("Expected a valid Date instance");
  }

  return date.toISOString();
}
Take Quiz

Real Codebase Usage

In production code, date validation is often placed at boundaries: when input enters a function, API handler, service, or database layer.

A guard clause keeps the main logic simple:

function createAppointment(startsAt) {
  if (!isValidDate(startsAt)) {
    throw new TypeError("startsAt must be a valid Date");
  }

  return {
    startsAt: startsAt.toISOString(),
    createdAt: new Date().toISOString()
  };
}

For applications that receive text input, separate the two responsibilities:

  1. Parse or construct a Date from the input.
  2. Validate the resulting Date instance.
const startsAt = new Date(userInput);

if (!isValidDate(startsAt)) {
  return { error: "Enter a valid date." };
}

This makes function contracts clear: a function either accepts raw strings and parses them, or it accepts already-created, valid Date objects.

Common Mistakes

Checking only instanceof Date

This accepts invalid dates:

function isDate(value) {
  return value instanceof Date;
}

isDate(new Date("bad input")); // true — not enough

Also test the time value.

Comparing getTime() with NaN

NaN is not equal to anything, including itself:

const date = new Date("bad input");

console.log(date.getTime() === NaN); // false

Use Number.isNaN(date.getTime()) instead.

Using global isNaN() without understanding coercion

Global isNaN() converts its argument to a number first:

isNaN("hello"); // true

For a timestamp returned by getTime(), it works, but Number.isNaN() is more precise and communicates your intent.

Using toString() as validation

String(date) !== "Invalid Date";

This relies on formatted output rather than the underlying timestamp. Prefer getTime().

Assuming Date.parse() validates every date format

Date.parse() can help parse strings, but support for non-standard date formats can vary. Prefer a clearly defined input format, such as an ISO 8601 format required by your application, then validate the resulting Date.

Comparisons

CheckWhat it answersSuitable for validity?
typeof value === "object"Is it broadly an object?No
value instanceof DateIs it a Date from this JavaScript realm?Only partly
value.getTime()What timestamp does the date hold?Yes, with Number.isNaN()
Date.parse(text)Can JavaScript parse this text into a timestamp?Useful for text, not for an existing Date
date.toString()How is the date displayed as text?Not recommended for validation

For most same-window or same-process code, use:

value instanceof Date && !Number.isNaN(value.getTime())

If a date might come from another browser frame or realm, instanceof Date can return false even for a real date. In that situation, call the built-in method directly:

function isValidDate(value) {
  try {
    return !Number.isNaN(Date.prototype.getTime.call(value));
  } catch {
    return false;
  }
}

Date.prototype.getTime.call(value) throws for values that are not real Date objects, while it works for valid and invalid Date objects from another realm.

Take Quiz

Cheat Sheet

// Standard same-realm validation
function isValidDate(value) {
  return value instanceof Date && !Number.isNaN(value.getTime());
}
// Cross-realm-friendly validation
function isValidDate(value) {
  try {
    return !Number.isNaN(Date.prototype.getTime.call(value));
  } catch {
    return false;
  }
}
  • Valid Date → date.getTime() is a number.
  • Invalid Date → date.getTime() is NaN.
  • new Date("invalid") is still a Date object.
  • Never test value === NaN or value.getTime() === NaN.
  • Use Number.isNaN() rather than relying on formatted text such as "Invalid Date".
  • Validate date strings separately from date instances.

FAQ

Why is new Date("bad value") instanceof Date true?

The constructor still returns a Date object. Its internal timestamp is NaN, which marks it as invalid.

How do I check whether a JavaScript date is invalid?

Use Number.isNaN(date.getTime()). It returns true for an invalid Date.

Is date.toString() === "Invalid Date" safe?

It usually identifies an invalid date, but it is better to check the timestamp with getTime(), which directly tests the date value.

Why does date.getTime() === NaN return false?

By JavaScript rules, NaN is not equal to any value, including another NaN. Use Number.isNaN().

Should my API accept date strings or Date instances?

Either can be appropriate, but choose one contract clearly. Date strings are easier to transmit over JSON; Date instances are convenient inside JavaScript code. Validate at the boundary either way.

Does Date.parse() validate a Date object?

No. Date.parse() accepts a string and returns a timestamp or NaN. For an existing Date, use getTime().

Why can instanceof Date fail for a valid date from an iframe?

Each browser realm has its own Date constructor. A date created in another frame may not match the current frame's constructor. Use Date.prototype.getTime.call(value) in a try/catch when cross-realm values are expected.

Take Quiz

Mini Project

Description

Build a small appointment normalizer that accepts a Date instance, rejects invalid values, and returns a safe API-ready appointment object. This demonstrates date validation at an application boundary.

Goal

Create a function that validates an appointment start time before converting it to an ISO string.

Requirements

  1. Create an isValidDate function that accepts a value.
  2. Return true only for valid Date instances.
  3. Create a createAppointment function that accepts a title and start date.
  4. Throw a TypeError when the start date is invalid.
  5. Return an object containing the title and an ISO-formatted start time.
Take Quiz

Keep learning

Related questions

View more