user13734003
user13734003

Reputation:

Why moment(date).isValid() returns wrong result

when I check the following date it returns true result, Why?

const value = "3";
if (moment(new Date(value), "DD-MM-YYYY HH:mm", true).isValid())  // true
{ }

or

const value = "3";
if (moment(new Date(value)).isValid())  // true
{ }

Upvotes: 0

Views: 1755

Answers (3)

Mayank Pathela
Mayank Pathela

Reputation: 648

Because 3 is a valid Date, the Date also supports only the year or only month format.

If you try new Date("YYYY") --> It's a valid date If you try new Date("MM") --> It's a valid format

So, for new Date("{1 to 12}") It will accept

For new Date("{13 to 31}") It's invalid

Also, from new Date("{32 to 49}") It considers as year, for two digits it will add the current century that is (2000 + number you specified), for e.g. new Date("32") is the year 2032 and for new Date("{50 to 99}") it adds in the previous century i.e. (1900 + number you specified), for e.g. new Date("99") is the year "1999"

For three-digit, till "100000" on-wards it's pretty straightforward what input it is will be a year, for e.g. new Date("100") is year 100 and new Date("100000") is the year 100000. The rest are invalid.

The above is valid as of today, instead of taking care of the above information it's always advisable to use Null, NaN, and Undefined values where the date field is not present

Upvotes: 0

user120242
user120242

Reputation: 15268

This is one of those cases that shows you need to sanitize your date strings and should not depend on the native parser, unless you are sure your strings have already been validated and are conformant.

ECMA-262 Date(value) constructor specs
Date.parse

If the String does not conform to that format the function may fall back to any implementation-specific heuristics or implementation-specific date formats.

So it's not conformant to "Date Time String Format", which requires the string to start with "YYYY", so it goes to an implementation specific parsing that is similar to the rules for above, but using the form: "MM-DD-YYYY".

The purpose of using strict mode (setting third argument of moment() to true) is to let moment do the string parsing and determine if it fits the formats that you provide (to for example avoid unexpected parsing behavior like this). If you use Date() to parse, you are no longer using moment's strict mode to validate the string fits your required format.

let value = "3";

function checkDate(value){
console.log(value,
  moment(value, "DD-MM-YYYY HH:mm", true).isValid() ? 'valid' : 'invalid')
}

value = "01-01-2011 11:22"
checkDate(value)

value = "01-01-2011 11:22Z"
checkDate(value)

value = "3"
checkDate(value)

value = new Date("3").toString()
checkDate(value)

value = new Date('INVALID DATE')
checkDate(value)
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.25.3/moment-with-locales.min.js" integrity="sha256-8d6kI5cQEwofkZmaPTRbKgyD70GN5mDpTYNP9YWhTlI=" crossorigin="anonymous"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.28/moment-timezone-with-data.js" integrity="sha256-O1PdKrSbpAYWSBteb7yX/CMmHhu3US31mtCbsryGwaY=" crossorigin="anonymous"></script>

If you don't need to validate the date string (for example to prevent unexpected parsing behavior), don't need to worry about non-modern browsers, and really just need to parse conforming Date strings and format to basic string formats, you could just use native Date() with Intl.DateTimeFormat or Date.prototype.toLocaleString.
TL;DR the way you are using it right now implies that you don't actually need moment

Upvotes: 0

brk
brk

Reputation: 50291

That is because new Date("3") is valid date and

console.log(new Date("3"))

Upvotes: 5

Related Questions