5

How to validate a date? I mean not the format, but the logic. For example: Feb 30th is not a valid date.

var date = new Date("2015-02-29T13:02:49.073Z"); // 2015 Feb 29th does not exist
console.log(date.toISOString());

Returns 2015-03-01T13:02:49.073Z (March 1st).

But I want a information that this date (input) is not valid.

Edit: Tested in Chrome. Firefox returns "invalid date". But not on parsing. Only when the date is used (e.g. toISOString()) an exception is thrown.

try
{
  var date = new Date("2015-02-29T13:02:49.073Z");
  console.log(date.toISOString());
}
catch(e)
{
    console.log("error: " + e.message);
}

Firefox:

invalid date

Chrome:

(nothing, just switched to the next date.)

Summary: It is browser-dependent. So, not recommended to use.

jsfiddle example

Dominik
  • 429
  • 1
  • 7
  • 14
  • Stop: I see now that this depends on browser. Firefox returns invalid date and chrome ignores and count to next day. Ok but this is terrible. I have to write a own function to validate a date string. (?) – Dominik Mar 23 '16 at 13:41
  • _It is not recommended to use Date.parse as until **ES5**, parsing of strings was entirely implementation dependent. There are still many differences in how different hosts parse date strings, therefore date strings should be manually parsed (a library can help if many different formats are to be accommodated)._ ([ref.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse)) – hindmost Mar 23 '16 at 13:45
  • Is there a question here? The logic behind how the Date constructor deals with the various arguments is fully documented in [*ECMA-262*](http://ecma-international.org/ecma-262/6.0/index.html#sec-date-year-month-date-hours-minutes-seconds-ms). How to validate a date (i.e. the values) has been covered in [*many questions here*](http://stackoverflow.com/search?q=%5Bjavascript%5D+validate+a+date). – RobG Mar 23 '16 at 15:22
  • @RobG This is not exacly the same. The question is about the Date Object allows invalid data. Good to know that this depends on the browser. It has "nothing" to do with ECMA. It's a browser behaviour. This information is useful. But thanks for the links and your advice. – Dominik Mar 23 '16 at 16:55

6 Answers6

5

I use this function to check whether a date is valid or not:

function isValidDate(year, month, day) {
    month = month - 1;
    var d = new Date(year, month, day);
    if (d.getFullYear() == year && d.getMonth() == month && d.getDate() == day) {
      return true;
    }
    return false;
}
Keyne Viana
  • 6,194
  • 2
  • 24
  • 55
  • Yes, I also think that you have to do this. Just to parse with Date() is not enough. :) – Dominik Mar 23 '16 at 13:45
  • Note you may need to normalise and add timezone/daylight savings to this code as mentioned in my answer – mplungjan Mar 23 '16 at 13:46
  • @mplungjan—daylight saving can be ignored for dates (provided the browser doesn't have bugs). Only the month needs to be tested (since a date outside the month range and a month outside 1 to 12 inclusive will result in *getMonth* returning a different month number). – RobG Mar 23 '16 at 15:29
  • The date created can be around midnight and hence next day depending on time zone – mplungjan Mar 23 '16 at 15:34
4

The easiest thing I can think of, is to convert the parsed date to ISO string and compare it to the original input:

var input = "2015-02-29T13:02:49.073Z"
var date = new Date(input);
var isValid = (input === date.toISOString());
mplungjan
  • 169,008
  • 28
  • 173
  • 236
Jan
  • 2,060
  • 2
  • 29
  • 34
  • Yes, thanks for this. I just had the same idea. It's only works with same string format. But this is exactly this what I need. I already have a regex for validate the ISO String. – Dominik Mar 23 '16 at 17:01
1

I wrote small function for you:

function check_date(str){
    try{
        return str == new Date(str).toISOString()
    }catch(e){
        return false;
    }
}

Try this

console.log(check_date('2015-02-01T13:02:49.073Z'));
console.log(check_date('2015-02-35T13:02:49.073Z'));
console.log(check_date('2015-02-29T13:02:49.073Z'));

https://jsfiddle.net/8o040ctr/

Veniamin
  • 459
  • 2
  • 9
0

I've found that behavior rather amusing. I used to just convert the input to a date (as you've done), then update the text in the textbox to show the date as interpreted by JavaScript so the user would see the resulting (valid) date.

Luckily, we can do much better now. Moment.js is a fantastic library for dealing with date/time values in JavaScript. It's sure made life a lot easier for me!

http://momentjs.com/

Chris Bergin
  • 415
  • 2
  • 8
0

Dates in browsers are always very tricky, I suggest you to use a js lib like moment: http://momentjs.com/

then you can use .isValid() method for ex.:

moment('03:55', 'HH:mm').isValid(); 
moment('2012-05-25', 'YYYY-MM-DD').isValid();
moment('2015-02-29T13:02:49.073Z', "YYYY-MM-DDTHH:mm:ss", true).isValid();
thegio
  • 1,233
  • 7
  • 27
0

If you pass a string that starts with 'YYYY-MM' format, like you have in the question, you could use this function:

function makeDate(s) {
    var date = new Date(s);
    if (date.toISOString(date).substr(0,7) != s.substr(0,7)) throw "Invalid date";
    return date;
}

dt = makeDate('2015-02-29T13:02:49.073Z');

This makeDate function would replace the plain new Date(...) call, but will also throw an error in Chrome when it is passed an invalid date string.

trincot
  • 317,000
  • 35
  • 244
  • 286