0

I have a date string that is formatted depending on the language/locale of the browser. For example, "03/05/2019" in en-US is March 5, 2019 (mm/dd/yyyy) but in en-NZ, it's May 3, 2019 (dd/mm/yyyy).

I need to know how to convert the string to date using JavaScript with the corresponding locale. I cannot hardcode the format because the locale really depends on the browser. I tried using Moment.js but I cannot seem to make it work. It returns invalid date for dates like "16/05/2019". It looks like it's not following the locale which I set to en-NZ.

Here is the momentjs code that I have tried:

moment().locale('en-NZ').format('L')

This will return the en-NZ format of the current date which is 27/05/2019 but when I try to include a date string:

moment('16/05/2019').locale('en-NZ').format('L')

This returns 'Invalid Date'. Any suggestions on how to do it or even a different plugin that I can use? Thanks.

  • You should edit the question and add the code you are using. – Koby Douek May 27 '19 at 11:00
  • 1
    Sorry, but trying to guess the format that a user will enter a date based on the browser **language** is seriously flawed. Some browsers will default to en-US regardless of system settings. Also, users aren't necessarily using a device that they can set the system settings to their preferred language or formats. And lastly, most systems allow date formats to be set independently of the language, so you can't reliably determine one based on the other. E.g. A person might use short dates like 28/2/2019, but long dates like February 28, 2019. What do you make of that? – RobG May 27 '19 at 11:37

4 Answers4

1

Thank you for your suggestions but I think I found a solution and answered my own question. I was using momentjs incorrectly. The date, long date format, and locale are all parameters of the moment function. Therefore, it identified the date correctly and now, I can format it to any format I want. (assuming you have a code to get the browser locale like what @Dean Meehan suggested)

new Date(moment('16/05/2019','L','en-nz').format('MM/DD/YYYY'))

So 16/05/2019 on en-NZ is read as May 16, 2019.

  • this is the right way to use Moment's constructor, but I will say it's a little strange to pass the result of `format` to the native date constructor. You should instead do `moment(...).toDate()` – snickersnack Sep 30 '19 at 04:20
0

Per http://momentjs.com/docs/#/parsing/string-format/ you need to pass the format:

If you know the format of an input string, you can use that to parse a moment.

moment("12-25-1995", "MM-DD-YYYY");

The parser ignores non-alphanumeric characters, so both of the following will return the same thing.

moment("12-25-1995", "MM-DD-YYYY");
moment("12/25/1995", "MM-DD-YYYY");

The parsing tokens are similar to the formatting tokens used in moment#format.

abelito
  • 1,094
  • 1
  • 7
  • 18
  • No, I do not know the format. What I do have is the locale code (en-US, en-NZ, etc.). So I was wondering how to get the format using the locale code. – Raphael Lajada May 27 '19 at 14:23
  • @RaphaelLajada I would suggest not doing that at all. Use moment().milliseconds() instead to get it from EPOCH. From there you can format the date however you like according to their Locale – abelito May 27 '19 at 14:40
0

Even though not ideal, there are a few ways in which to identify a date string.

In your case, I would try and use the language API available in newer browsers.

if(navigator.language=="en-US"){
    //USA Date Format
}else{
   //NZ Date Format
}

You could expand this using the full list of countries: https://en.wikipedia.org/wiki/Date_format_by_country

See Get Locale Short Date Format using javascript for a full list of languages and formats that could be used.

I would also advice using Luxon over Moment.JS as it is more future proof and supports locales.

Dean Meehan
  • 2,511
  • 22
  • 36
  • My `navigator.language` is `"en-US"` even though I'm in the UK on a UK-locale machine. It's not reliable. – T.J. Crowder May 27 '19 at 11:24
  • I would have provided a Luxon example, but I cannot currently test it; but it may run as expected out of the box. – Dean Meehan May 27 '19 at 11:24
  • @T.J.Crowder Is your computers language set to "en-US"? If so your date strings should come out as the USA date format. – Dean Meehan May 27 '19 at 11:25
  • My language is set to UK English and dates on my system are shown formatted in UK format. – T.J. Crowder May 27 '19 at 11:33
  • This is a good approach since navigator.language is what I use to get the locale but I'm not sure if putting all date formats in the code is efficient. Thank you though. I'll update this question once I apply the changes tomorrow. – Raphael Lajada May 27 '19 at 14:22
0

Unfortunately, the current user's locale is not well provided by a JavaScript-accessible API at present. This answer goes into some of it, but even here in 2019, Chrome doesn't support any of the properties listed there other than navigator.language, which isn't reliable (mine comes back as en-US, but I'm in the UK so it should be en-GB [everything on my system formats my dates in UK format]).

The only way I've found to get the local date format is to as Intl.DateTimeFormat to format a date and then work it out from the result:

const format = new Intl.DateTimeFormat()
  .format(new Date(2019, 11, 25)) // Christmas 2019
  .replace("2019", "YYYY")
  .replace("12", "MM")
  .replace("25", "DD");
console.log(format);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>

On my system, that returns DD/MM/YYYY because I'm in the UK which, like NZ, uses a rational format. (I'm part American, so I can kid Americans about their weird date format.) Presumably in the U.S. it would return MM/DD/YYYY.

You can then use that format with moment:

const format = new Intl.DateTimeFormat()
    .format(new Date(2019, 11, 25)) // Christmas 2019
    .replace("2019", "YYYY")
    .replace("12", "MM")
    .replace("25", "DD");

document.getElementById("btn").addEventListener("click", function() {
    const str = document.getElementById("date").value.trim();
    const dt = moment.utc(str, format);
    console.log(`The date in ISO format: ${dt.toISOString()}`);
});
Enter a date in your local format and click Parse It:
<input type="text" id="date" autofocus>
<input type="button" id="btn" value="Parse It">

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>

You might want to offer your users a box to select their locale, in which case you'd want moment-with-locales.min.js instead of moment.min.js above.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875