Validating UK dates with moment.js

Viewed 431

I need to validate UK dates, I'm using moment.js. The UK date format is "dd/mm/yyyy". The following code reports false validating the date "25/03/2021", why? How can I solve?

moment.locale("en");
const since = "25/03/2021";
let date = moment(since, "L");
let isValid = date.isValid();
console.log(isValid);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>

Update: I tried the solution of msmolcic but the problem is that I'm validating dates taken from the browser and when UK English is set the locale is "en" and not "en-GB". The following code fails.

How can I fix it?

moment.locale("en");
const since = "25/03/2021";
let date = moment(since, "L");
console.log(date);
let isValid = date.isValid();
console.log(isValid);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment-with-locales.min.js"></script>

4 Answers

There are two things wrong with your example:

  1. You included moment.min.js, but to work with locales you have to include moment-with-locales.min.js.
  2. You have to set locale to en-GB instead of just en.

moment.locale("en-GB");
const since = "25/03/2021";
let date = moment(since, "L");
console.log(date);
let isValid = date.isValid();
console.log(isValid);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment-with-locales.min.js"></script>

In addition to @msmolcic I would add that you could also use the ISO standard, which will be validated. If you're creating a more serious app with a backend, simply store the Date object in ISO format and in the front end simply execute moment(dateHere).format("dd/mm/yyyy");

The Magic happens inside the constructor. If you pass a pattern into it then moment will parse it correctly.

 const since = "25/03/2021";
let date = moment(since, "DD/MM/YYYY");
console.log(date);
let isValid = date.isValid();
console.log(isValid);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>

Having read the comments and the exact nature of your problem I think you want to achieve the following:

  1. Get the user's xx-XX style locale from the browser
  2. Check a date for validity using moment.js

As you've read in the other answers, the locale en resolves to en-US for moment.js. Therefore we want the user's preferred xx-XX style locale. Instead of just getting navigator.language, we can check all preferred locales in order using navigator.languages (note the extra s). To get the xx-XX style locale:

const locales = navigator.languages || [navigator.language] // since navigator.languages may be undefined
console.log(locales)

const preferredLocale = locales.filter(lang => lang.match(/\S+-\S+/))[0]
console.log(`The user's preferred locale is ${preferredLocale}`)

Of course, the browser may not have any xx-XX style locale set in its list of preferred locales. In that case, the only way would be to check either the Accept-Language HTTP header, or through IP geolocation. However, those may be a bit farfetched for this purpose. But feel free to check here for more information on this.

Consequentially, you can then use @msmolcic's answer to combine this for your solution:

const locales = navigator.languages || [navigator.language] // since navigator.languages may be undefined
const preferredLocale = locales.filter(lang => lang.match(/\S+-\S+/))[0]

moment.locale(preferredLocale)
const since = "25/03/2021"
let date = moment(since, "L")

let isValid = date.isValid()
console.log(`The date is ${isValid ? 'valid' : 'not valid'}`)
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment-with-locales.min.js"></script>

Related