标签云

微信群

扫码加入我们

WeChat QR Code

I'd like to tell the difference between valid and invalid date objects in JS, but couldn't figure out how:var d = new Date("foo");console.log(d.toString()); // shows 'Invalid Date'console.log(typeof d); // shows 'object'console.log(d instanceof Date); // shows 'true'Any ideas for writing an isValidDate function?Ash recommended Date.parse for parsing date strings, which gives an authoritative way to check if the date string is valid.What I would prefer, if possible, is have my API accept a Date instance and to be able to check/assert whether it's valid or not. Borgar's solution does that, but I need to test it across browsers. I also wonder whether there's a more elegant way.Ash made me consider not having my API accept Date instances at all, this would be easiest to validate.Borgar suggested testing for a Date instance, and then testing for the Date's time value. If the date is invalid, the time value is NaN. I checked with ECMA-262 and this behavior is in the standard, which is exactly what I'm looking for.


You could remove the if statement by changing the body of the function to: return ( Object.prototype.toString.call(d) === "[object Date]" && !isNaN(d.getTime()) );

2019年05月23日47分21秒

styfle - guess it's a style preference: I find it clearer to separate the type check from the equality logic.

2019年05月24日47分21秒

orip discourse is exactly what is heavily discouraged in questions. Please refer to relevant meta topics to learn the rationale behind it. Placing an answer to own question in the question itself is against the site policy. OTOH, thanking for responses and having "EDIT" in your answer is typicalfluff. If you want you top-rated question to identify you as a person who doesn't know what SO is and how to use it, and doesn't wish to learn that - be my guest.

2019年05月24日47分21秒

orip: It was not "lost"; it is still cluttering up the question's revision history if you want to see it again. But it does not belong in a question. At 37k rep you should know this.

2019年05月24日47分21秒

Kindly stop the edit war. The edits on this question are discussed on meta. Please do not edit/rollback this post further. If you disagree with previous edits/rollbacks or have any comments regarding them, please post on that meta thread and not here.

2019年05月24日47分21秒

instanceof breaks across frames. Duck-typing can work just fine too: validDate == d && d.getTime && !isNaN(d.getTime()); -- Since the question is for a general utility function I prefer to be more strict.

2019年05月24日47分21秒

Borgar,just found my answer: "The problems arise when it comes to scripting in multi-frame DOM environments. In a nutshell, Array objects created within one iframe do not share [[Prototype]]’s with arrays created within another iframe. Their constructors are different objects and so both instanceof and constructor checks fail."

2019年05月24日47分21秒

you don't even need d.getTime just isNan(d)

2019年05月23日47分21秒

Could be simplified like this: d instanceof Date && !isNaN(d.getTime())

2019年05月23日47分21秒

Thanks for the answer, but I wish to stress Borgar and blueprintChris comments: if I parse the digit 1 for example I would still have a valid date resulting to Mon Jan 01 2001 00:00:00 which is indeed a date, however for the purpose of my application it is completely useless. Thus, there is some more input validation needed in my case at least. This answer validates a dateObject not a Date!

2019年05月24日47分21秒

-1 Dunno why this has so many up votes, Date.parse is implementation dependent and definitely not to be trusted to parse general date strings. There is no single format that is parsed correctly in popular browsers, much less all those in use (though eventually the ISO8601 format specified in ES5 should be ok).

2019年05月24日47分21秒

Try this in chrome -Object.prototype.toString.call(new Date("2013-07-09T19:07:9Z")). It will return "[object Date]".According to you, therefore, "2013-07-09T19:07:9Z", should be a valid date.But it is not.You can verify it, again in chrome, by doing var dateStr = new Date("2013-07-09T19:07:9Z"); dateStr It will return invalid date.

2019年05月23日47分21秒

Tintin: that's what isFinite() is for - toString.call() is only a replacement for the instanceof part of the check

2019年05月24日47分21秒

Will comparing with '[object Date]' work with non-english browsers?I doubt it.

2019年05月23日47分21秒

kristianp actually it probably will and is probably even part of the ECMAScript spec. But, yes, it seems ugly.

2019年05月24日47分21秒

To me the first approach here is the very best option, although I'm not sure if there's any real-world advantage of using isFinite over isNaN (both work just fine with Date(Infinity)). Furthermore, if you want the opposite condition, it gets a bit simpler: if (!(date instanceof Date) || isNaN(date)).

2019年05月23日47分21秒

isNaN is a more explicit way to test for NaN

2019年05月24日47分21秒

And yet, you always find people writing their own versions :)documentcloud.github.com/underscore/docs/…

2019年05月23日47分21秒

since I respect underscore.js this prompted some research. isNaN("a") === true, while ("a" !== "a") === false. It's worth thinking about. +1

2019年05月24日47分21秒

I tested the performance for the 3 main solutions I have found here. Congrats, you are the winner! jsperf.com/detecting-an-invalid-date

2019年05月24日47分21秒

Ali That is a valid date object.new Date("02-31-2000") // Thu Mar 02 2000 00:00:00 GMT+0000 (GMT Standard Time). If you are passing in a string to the date constructor, you must pass in a standardised string to get a reliable result. Specifically, "The string should be in a format recognized by the Date.parse() method". developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

2019年05月23日47分21秒

The only problem is if date is not of type Date; you get a JS error.

2019年05月23日47分21秒

Andrew you need to create the date Objectand if you already have an object then use date &&!isNaN(date.getTime())

2019年05月24日47分21秒

That still gives you a JS error if date is not of type Date. For example: var date = 4; date && !isNaN(date.getTime());.

2019年05月24日47分21秒

Andrew usedateinstanceof Date && !isNaN(date.getTime())

2019年05月24日47分21秒

Right, like the other answers from 8 years ago. :P stackoverflow.com/a/1353945/2321042

2019年05月23日47分21秒

Best solution, extremely easy to implement , works with any formatting (my case is dd/MM/yyyy), also knows the leap years and doesn't convert invalid dates (i.e. 29/02/2015) into valid ones by itself (i.e. 30/03/2015). To check a date in the formad dd/MM/yyyy I've just had to use moment("11/06/1986", "DD/MM/YYYY").isValid();

2019年05月24日47分21秒

This use of Moment has been deprecated :(

2019年05月24日47分21秒

JamesSumners how/why?

2019年05月24日47分21秒

This use has not been depreciated. Calling moment(input) without a format string is depreciated (unless the input is ISO formatted).

2019年05月24日47分21秒

This method can be extremely slow when processing many dates.Better to use a regex in those cases.

2019年05月24日47分21秒

Upvote for being the first answer working with non english / locale date formats.

2019年05月24日47分21秒

Extending the prototype? That's a big JavaScript no no!

2019年05月24日47分21秒

It's the same Borgar wrote 2 years ago... What's new??

2019年05月23日47分21秒

It's two lines instead of ugly nested if statements.

2019年05月23日47分21秒

str isn't being used.

2019年05月23日47分21秒

could you explain what is happening in your code?

2019年05月23日47分21秒

From MDN: "The Date.parse() method parses a string representation of a date, and returns the number of milliseconds since January 1, 1970, 00:00:00 UTC or NaN..." So running a potential date through this function returns either an integer or NaN. Then the isNaN() function will give a clean boolean telling you whether the original value was a valid date object or not. This is enough to make a spot check, but the example above then attaches this method to the Date object to make the functionality easily available and readable throughout your program.

2019年05月23日47分21秒

if d is boolean you will receive 0 or 1 that not is a Nan !!

2019年05月24日47分21秒

isNaN(new Date(...)) - the simple and short method

2019年05月24日47分21秒

MiF yes, I update my answer with your suggestion ;) thanks

2019年05月23日47分21秒

This returns true for when testing a date object that has been initialized with an Invalid Date.

2019年05月24日47分21秒

I believe this is browser dependent.

2019年05月24日47分21秒

barrypicker What do you mean this is browser dependent?

2019年05月24日47分21秒

(new Date('2/30/2014')).valid() returns true

2019年05月24日47分21秒

Been a while since I've answered this but you may need both return conditions, including the && value.split('/')[0] == (d.getMonth()+1);

2019年05月24日47分21秒

Ok, but this tests if a string is a date in a M/D/Y format, not "the difference between valid and invalid date objects". It's not really what this is question about.

2019年05月23日47分21秒

the reason why its checked against the format is to check if the date has changed after it was parsed

2019年05月23日47分21秒

Isn't the OP asking for a method to return a Boolean, not a formatted string?

2019年05月23日47分21秒

The sample code does return a boolean, the formating plays a part in testing for some of the invalid cases.

2019年05月23日47分21秒

This one seems to work with leap year.

2019年05月24日47分21秒

But... methods above (Borgar's and the others) already checks for this type of validity... I can't get the issue.

2019年05月23日47分21秒

Borgar's doesn't - see his own comment to his answer.

2019年05月24日47分21秒

This solution only works when your country uses the dd/MM/yyyy notation. Also, it returns true when it's valid & 'Invalid date!' if it's not, better return 1 type only.

2019年05月24日47分21秒

This doesn't work !isNaN(new Date("2/30/2012").getTime()) returns true

2019年05月24日47分21秒

The question asked for how to find invalid Date instances, not strings, and besides: who says a date can't be delimited by something other than a forward-slash?

2019年05月23日47分21秒

Please edit this to provide some more background/explanation of the various bits of "magic" that you're performing.

2019年05月24日47分21秒

consider +date as date.toNumber ( actually there is no .toNumber method ) and parseInt(date) !== +date, parseInt(date) === NaN. "+" operator is a magic in js. and not cross-browser: try this: [new Date(Date.now()) + 1, +new Date(Date.now()) + 1]

2019年05月24日47分21秒