41

I would like to test if a date and or time entered is valid.

Can this be done with moment as date and time testing with javascript seems a nightmare. (have spent hours on this).

Test data looks like this.

Invalid

invalid = ""
invalid = " "
invalid = "x"
invalid = "1/1"
invalid = "30/2/2015"
invalid = "2/30/2015"

Is Valid

isvalid = "1/12/2015"
isvalid = "1/12/2015 1:00 PM";

Have tried various javascript methods with hours of trials failing.

I thought moment would have something for this. So tried the following, all of which does not work because I do no think moment works like this.

var valid = moment(input).isDate()
var valid = moment().isDate(input)

My time format is "dd/mm/yyyy"

Valamas
  • 24,169
  • 25
  • 107
  • 177
  • http://stackoverflow.com/questions/1353684/detecting-an-invalid-date-date-instance-in-javascript – norway-firemen Jan 30 '15 at 01:42
  • again, this is checking if an object is a date object – Valamas Jan 30 '15 at 01:49
  • I don't think the downvoter read my question very well; if they had given the time to read my question properly and see the accepted answer.... – Valamas Jan 30 '15 at 01:54
  • There is also a [.isValid()](http://momentjs.com/docs/#/parsing/is-valid/) function built into moment, but it validates very loosely. Are you doing any sort of form validation? If so, I would use a regex to validate your dates. Edit: moment does strict parsing as well: http://stackoverflow.com/a/24392357/831803 – norway-firemen Jan 30 '15 at 02:06
  • appreciate this is an old question but would you consider changing the accepted answer to the one referencing isValid(). I'd like to dupe something else here but the accepted answer is no longer the best. – 9bO3av5fw5 May 08 '20 at 13:59

3 Answers3

104

Moment has a function called isValid.

You want to use this function along with the target date format and the strict parsing parameter to true (otherwise your validation might not be consistent) to delegate to the library all the needed checks (like leap years):

var dateFormat = "DD/MM/YYYY";
moment("28/02/2011", dateFormat, true).isValid(); // return true
moment("29/02/2011", dateFormat, true).isValid(); // return false: February 29th of 2011 does not exist, because 2011 is not a leap year
Liam
  • 27,717
  • 28
  • 128
  • 190
Luca Fagioli
  • 12,722
  • 5
  • 59
  • 57
  • 9
    I think this answer should be the accepted answer. The isValid() function is able to handle things like leap years and such and you're not doing all the string comparisons like in the currently accepted answer. – Mnebuerquo Jan 14 '16 at 13:40
  • 6
    You may need to use the 3rd argument as well: As of version 2.3.0, you may specify a boolean for the last argument to make Moment use strict parsing. http://stackoverflow.com/questions/19978953/moment-js-isvalid-function-not-doing-properly/19979768#answer-19979768 – pulkitsinghal Mar 24 '16 at 18:45
  • 1
    The comment above is very important, see example: `var dateFormat = 'DD.MM.YYYY'; var givendate = '12'; alert(moment(givendate, dateFormat).isValid()); // true! alert(moment(givendate, dateFormat, true).isValid()); // false` – Avatar May 30 '16 at 12:13
  • 1
    this is checking only format. 30/02/2016 is not a valid date.but moment isValid() function return true – Coder Oct 14 '16 at 07:43
  • @nikhil moment("30/02/2016", "DD/MM/YYYY", true) return false. Read carefully the answer: you need to pass also the date format. – Luca Fagioli Oct 14 '16 at 14:00
  • @Luca Fagioli moment("01/02/0000", 'DD/MM/YYYY', true).isValid() return true – Coder Oct 18 '16 at 09:45
  • 1
    @Nikhil "01/02/0000" is a valid date. – Luca Fagioli Oct 18 '16 at 14:06
  • 'moment("11/25/2016 18:30","MM/dd/yyyy HH:mm",true).isValid()' is returning false. why? do I have to specify the time format also? – R K Sharma Nov 23 '16 at 05:28
  • 1
    @R K Sharma dd and yyyy are invalid tokens. You should use DD and YYYY instead. So moment("11/25/2016 18:30","MM/DD/YYYY HH:mm",true).isValid() returns true. – Luca Fagioli Nov 23 '16 at 11:05
  • 1
    Many date formats are also supported, Like `moment('2017-09', ['YYYY-MM', 'YYYY-MM-DD', 'MM-DD-YYY'], true)` https://momentjs.com/docs/#/parsing/string-formats/ – Green Sep 20 '17 at 04:20
38

Yes, you could use momentjs to parse it and compare it back with the string

function isValidDate(str) {
  var d = moment(str,'D/M/YYYY');
  if(d == null || !d.isValid()) return false;

  return str.indexOf(d.format('D/M/YYYY')) >= 0 
      || str.indexOf(d.format('DD/MM/YYYY')) >= 0
      || str.indexOf(d.format('D/M/YY')) >= 0 
      || str.indexOf(d.format('DD/MM/YY')) >= 0;
}

Test code

tests = ['',' ','x','1/1','1/12/2015','1/12/2015 1:00 PM']
for(var z in tests) {
  var test = tests[z];
  console.log('"' + test + '" ' + isValidDate(test));
}

Output

 "" false
 " " false
 "x" false
 "1/1" false
 "1/12/2015" true
 "1/12/2015 1:00 PM" true
Valamas
  • 24,169
  • 25
  • 107
  • 177
Kokizzu
  • 24,974
  • 37
  • 137
  • 233
-3

You can use the Date.parse() function.

Here is the details of how to use.

user48447
  • 35
  • 2
  • 4
    Date.parse('2/30/2011') returns as valid. 30th Feb or 2nd of the 30th month should be invalid. – Valamas Jan 30 '15 at 01:45
  • 3
    When including a link it's helpful to also include the relevant snippet in case the link is broken in future etc – Karl Jan 30 '15 at 01:47
  • `Date.parse('foo-bar 2014');` returns `NaN` which I find better than `new Date('foo-bar 2014').toString();` that returns `"Invalid Date"` – Amio.io Jan 10 '17 at 10:08