Kelok Chan
Kelok Chan

Reputation: 756

DayJS isValid behaves differently to Moment

I was trying to validate birthday using dayjs but its isValid is returning true for a date that doesn't exist. Funnily enough, the isValid by moment is working just fine.

dayjs('2019/02/31', 'YYYY/MM/DD').isValid() // true
moment('2019/02/31', 'YYYY/MM/DD').isValid() // false

I can't switch to moment because of the lightweightness of dayjs

Any idea how to tackle this?

Upvotes: 12

Views: 24298

Answers (6)

Willian
Willian

Reputation: 3405

Unfortunately, we can't rely on isValid() function that is provided in dayjs.

What I did, was to create a file utils called date-utils.ts. This file is a wrapper around the lib and add more validations on top of it.

Essentially, this statement will do the work we need:

  // it validates the string date properly
  if (Number.isNaN(new Date(date).getTime())) {
    return false;
  }

Then, you could create a file like the typescript example (feel free to make it js if you want).

// date-utils.ts
import dayjs from 'dayjs';

const isValid = (date: string) => {
  if (!date) {
    return false;
  }

  // it validates the string date properly
  if (Number.isNaN(new Date(date).getTime())) {
    return false;
  }

  return dayjs(date).isValid();
};

const getDate = (date: string) => {
  if (!date) {
    throw Error('The date is required.');
  }

  if (!isValid(date)) {
    throw Error(`The date "${date}" is not valid.`);
  }

  return dayjs(date);
};

export default { isValid, getDate };

Upvotes: 0

Asanka Siriwardena
Asanka Siriwardena

Reputation: 961

use strict mode

dayjs('2019/02/31', 'YYYY/MM/DD', true).isValid() //false

enter image description here

When strict mode is not enforced enter image description here

Note: you have to extend customParseFormat plugin as a prerequisite

Upvotes: 0

adif maulana
adif maulana

Reputation: 31

You can use customParseFormat plugin from day.js I do this on my react project and this is work perfectly fine.

import dayjs from 'dayjs';
import customParseFormat from 'dayjs/plugin/customParseFormat';

dayjs.extend(customParseFormat);

dayjs('30-02-2022', 'DD-MM-YYYY', true).isValid() // false

Upvotes: 3

blert
blert

Reputation: 352

August 2021: It's now possible to detect with .isValid() method these invalid dates passing a third parameter as true to dayjs constructor:

dayjs('2019/02/31', 'YYYY/MM/DD').isValid() // true
dayjs('2019/02/31', 'YYYY/MM/DD',true).isValid() // false

More information on this strict parsing argument can be found now at official doc.

NOTE: In Node.js I had to load first customParseFormat plugin before calling isValid() to receive expected validity results:

const dayjs = require("dayjs");
var customParseFormat = require("dayjs/plugin/customParseFormat");
dayjs.extend(customParseFormat);

Upvotes: 12

zhuber
zhuber

Reputation: 5524

Please look at this thread. Basically isValid doesn't validate if passed date is exists, it just validates that date was parsed correctly.

I'm not exactly sure if this works in all scenarios (especially if you have localization), but you could try something like:

function validate(date, format) {
  return dayjs(date, format).format(format) === date;
}

validate('2019/02/31', 'YYYY/MM/DD') // false

Reason for this kind of check is that

dayjs('2019/02/31', 'YYYY/MM/DD').format('YYYY/MM/DD')

returns 2019/03/03. Then when you compare it to your initial date (you should be able because formatting is the same) you should get the same value - and in this case you don't.

Upvotes: 7

Mosè Raguzzini
Mosè Raguzzini

Reputation: 15841

How moment.isValid() works (overflow checks)

If the moment that results from the parsed input does not exist, moment#isValid will return false.

How dayjs.isValid() works

If you look at the source code:

src/index.js

this.$d = parseDate(cfg) // Line 75
// ...
isValid() { // Line 96
  return !(this.$d.toString() === C.INVALID_DATE_STRING)
}

src/constant.js

export const INVALID_DATE_STRING = 'Invalid Date'

If you look to the source parse is not a straighforward Date.parse() because it take in consideration locale, date format and so on, but it seems that every valid date passed to Date() or Date.parse() are valid.

Date.parse('2019/02/31') // 1551567600000
new Date(2019/02/31) // Thu Jan 01 1970 01:00:00 GMT+0100

Upvotes: 1

Related Questions