Lodash isDate and Invalid NaN Date Instances

In JavaScript, managing date objects often leads to subtle bugs when a Date instance is created with invalid arguments, resulting in an "Invalid Date" object whose .getTime() returns NaN. While developers often reach for utility libraries to sanitize inputs, Lodash’s _.isDate function serves primarily as an object-type guard rather than a temporal validity validator. This article explains how _.isDate evaluates date instances, why it allows NaN timestamps to pass, and the exact patterns required to ensure a date is both an instance of Date and temporally valid.

Type Guarding vs. Validity Checking

Lodash’s _.isDate is designed to verify whether an input is an object classified as a Date. Internally, it inspects the internal [[Class]] tag of the value using Object.prototype.toString.call(value):

function isDate(value) {
  return isObjectLike(value) && baseGetTag(value) == '[object Date]';
}

Because of this design, _.isDate does not verify if the internal timestamp is valid. An invalid date created via new Date('invalid-string') is still fundamentally a Date instance. As a result:

const invalidDate = new Date('not a real date');

console.log(_.isDate(invalidDate)); // true
console.log(invalidDate.getTime());  // NaN

_.isDate protects your code from primitive types, null references, plain objects, or strings masquerading as dates. However, it does not prevent an instance from yielding NaN when queried for its time.

How to Protect Against Invalid Date Instances

To completely guard an application from processing NaN time values, _.isDate must be paired with a check against the instance's numeric representation.

Method 1: Combining _.isDate with .getTime()

The most direct approach checks that the object is a recognized Date and that its internal epoch time is a valid number:

function isValidDate(value) {
  return _.isDate(value) && !Number.isNaN(value.getTime());
}

isValidDate(new Date());                   // true
isValidDate(new Date('invalid-string'));   // false
isValidDate('2026-01-01');                 // false

Calling .getTime() returns the number of milliseconds since January 1, 1970, UTC. If the date is invalid, it returns NaN. Number.isNaN() accurately detects this state, ensuring only valid dates proceed.

Method 2: Coercion via Number()

Another common pattern involves numeric coercion:

function isValidDate(value) {
  return _.isDate(value) && !isNaN(Number(value));
}

When a Date object is passed to Number(), JavaScript internally invokes Date.prototype.valueOf(), which returns the same value as .getTime().

Summary

Lodash's _.isDate protects exclusively against type mismatches by verifying the internal [object Date] tag. It does not protect against instances that return NaN for their time. To ensure that an object is both a Date instance and represents a valid point in time, always combine _.isDate(value) with !Number.isNaN(value.getTime()).