Richard
Richard

Reputation: 6126

Using Moment to Validate Default Javascript Date Format

I want to use moment (or any other method) to validate a particular string as a valid date value based on the default javascript date format.

I have the following code:

var date = new Date(); // Tue Nov 28 2017 17:54:41 GMT-0600 (CST)

I want to take that string output and use moment to validate that as a valid date string. I know I can do this:

moment(date, moment.ISO_8601).isValid();

But there is a problem. Here are the results for the same date values:

moment(new Date(), moment.ISO_8601).isValid(); //True
moment("Tue Nov 28 2017 17:54:41 GMT-0600 (CST)", moment.ISO_8601).isValid() //False

Which is not what I want since both of them should be true. I can't do new Date(...) because here's the results for that approach:

moment(new Date("Tue Nov 28 2017 17:54:41 GMT-0600 (CST)"), moment.ISO_8601).isValid(); //True
moment(new Date("3"), moment.ISO_8601).isValid(); //True

This also is not what I want since the second line should be false.

How do I properly valid a string as a valid date only if it strictly follows the format Tue Nov 28 2017 17:54:41 GMT-0600 (CST)?

I have researched everywhere to understand what format Tue Nov 28 2017 17:54:41 GMT-0600 (CST) is but I can't find anything. It's not ISO 8601 and not RFC 2822 either.

Upvotes: 1

Views: 1134

Answers (2)

VincenzoC
VincenzoC

Reputation: 31502

As RobG stated in the comments There is no "default javascript date format". The output from Date.prototype.toString is implementation dependent

Since your input is neither in ISO 8601 nor in RFC 2822 Date time formats you have to use moment(String, String) using 'ddd MMM D YYYY HH:mm:ss [GMT]Z' as format parameter. If you want that your string matches strictly your format, you can use strict mode (moment(String, String, Boolean)).

Please note that moment does not provide token for parsing timezone abbreviation (e.g. CST), so your input will not be recognized in strict mode. Here an example of parsing using both strict and forgiving mode; myIsValid function is an example of removing timezone abbreviation from the input.

var s = 'Tue Nov 28 2017 17:54:41 GMT-0600 (CST)';
var fmt = 'ddd MMM D YYYY HH:mm:ss [GMT]Z';

console.log(moment(s, fmt).isValid());
console.log(moment(s, fmt, true).isValid());

function myIsValid(input){
  // Check if input contains ()
  var idxl = input.indexOf('(');
  var idxr = input.indexOf(')');
  if( idxl>0 && idxr>0 ){
    // Remove timezone abbreviation
    input = input.substr(0, idxl-1);
  }
  var fmt = 'ddd MMM D YYYY HH:mm:ss [GMT]Z';
  return moment(input, fmt, true).isValid();
}

console.log(myIsValid(s));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>


Lastest version of moment (2.19.2), gives Invalid Date even with forgiving mode. Using parsingFlags() you see that weekdayMismatch is true, I think this is an issue of the 2.19+ version of moment this is related to moment #4227 issue.

var s = 'Tue Nov 28 2017 17:54:41 GMT-0600 (CST)';
var fmt = 'ddd MMM D YYYY HH:mm:ss [GMT]Z';
var m1 = moment(s, fmt);
var m2 = moment(s, fmt, true);
console.log(m1.isValid());
console.log(m1.parsingFlags());
console.log(m2.isValid());
console.log(m2.parsingFlags());
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.19.2/moment.min.js"></script>

Upvotes: 1

RobG
RobG

Reputation: 147553

If you want to strictly validate a timestamp with Moment.js, use the strict flag when parsing:

var s = 'Tue Nov 28 2017 17:54:41 GMT-0600';
s = s.replace('GMT','');
console.log('Modified string: ' + s);

var mStrict = moment(s, 'ddd MMM D YYYY HH:mm:ss ZZ', true);
console.log('Strict parse: ' + mStrict.format());

var mLoose  = moment(s, 'ddd MMM D YYYY HH:mm:ss ZZ');
console.log('Loose parse : ' + mLoose.format());
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.19.2/moment.min.js"></script>

However, for me both strict and loose produce "Invalid date", which is incorrect (and should be "Invalid Date"). The issue seems to be the timezone value or token.

Upvotes: 1

Related Questions