Today, the only way to check if a Date is a valid Date is through the !isNaN(new Date(someDate).getTime()) which is both not readable and also takes a while to understand (especially for new devs) what is it really doing.
My proposal is to follow on the Array.isArray method and add a Date.isDate. The implementation of this function could follow the signature:
function isDate (date) => boolean
function isDate (string) => boolean
function isDate (number) => boolean
Accepting a Date constructor, a number (timestamp) or a string (ISOString) would then pass it to the actual date constructor, this is a (VERY SIMPLE DRAFT) implementation:
function isDate (maybeDate) {
switch (typeof maybeDate) {
case 'string':
case 'number':
const dateValue = new Date(maybeDate)
return !isNaN(dateValue.getTime())
case 'object':
if ('getTime' in maybeDate) return !isNaN(maybeDate.getTime())
return false
default:
return false
}
}
So the usage could be simplified and made available under the Date constructor as:
If you've not yet checked it out, soon there will be the Temporal API in JavaScript which will hopefully be able to replace all use cases for Date. Temporal documentation
Yeah, this was more of a proof of concept, the actual implementation would be much better than this, since instanceof can be tampered with, I think we could check like we do in the Date Mocks API from Node (https://github.com/nodejs/node/pull/48638/)
On the Temporal one, I'm super excited for it but it's a proposal that's been around for 5 years or more already... I get your point, we should have it in one API, but I think to wait until Temporal is ready may take years, and since this is a "simple" change, which is compliant to other APIs like Array.isArray, I wanted to vouch and defend the idea of this coming to the current API, at least until we have Temporal in place.
Dates can have invalid values. This isn't a check for "is a date", but "is a valid date, so a name like Date.isDate makes little sense.
Also, a date is valid if and only if its source can be parsed as a date value. So, logically speaking, Number.isNaN(Date.parse(someDate)) is currently the most direct way to check whether a given string is a valid date string. (It also has effectively zero memory overhead.)
For numbers, I don't see the point other than maybe exposing Date.MAX_TIME/Date.MIN_TIME. Testing is as easy as testing Math.abs(value) <= Date.MAX_TIME, which naturally fails for NaNs.
I see the logic here, thanks for the clarification. But I think that, from the developer/user pov it makes little to no difference what type we are testing, in this case, the point is to verify if the passed value would be a valid Date object in JavaScript, in this case we are both testing for valid values and, by definition, if it's a valid date, otherwise the Date object would also not accept it.
The naming of the function is just a mimic to the present Array.isArray from pior art, I'm not against changing it if it makes more sense. But, in the same spirit as the array, it tests if this would be a valid object in the end but abstracting from the deeper logic of what is a date and what is an internal date value.
Besides, I think writing:
if (Date.isDate(someValue)) { ... }
Is much more readable and easy to understand in a glimpse than:
if (!isNaN(new Date(someValue).getTime())) { ... }
So it makes the code easier to maintain and friendlier for other people as well.