Home » Javascript » Convert a date in navigator.locale format to database date

Convert a date in navigator.locale format to database date

Posted by: admin November 1, 2017 Leave a comment

Questions:

I have a date in an format defined by navigator.locale, so we do not know in advance which one it is.

In my case I have some french dates because my navigator languages is set to french. Indeed, if I check my browser supported languages I can see (using developer console inside my browser) :

> navigator.locales

['fr-FR', 'fr', 'en-US', 'en']

And if I check my current locale I get :

> navigator.locale

'fr'

In input I have a date that is stored in a variable :

> console.log(date)

20/12/2017

Which points to December, 20th of 2017.

So what I want is to retrieve the english representation of this date (which has an unknown format).

QUESTIONS

  1. How to create a Date() object from a unknown format using navigator.locale as the only hint for javascript ?
  2. Alternative, could we use Intl.DateTimeFormat to parse a date from a format using navigator.locale ?

Why I need to go from navigator.locale ?

I did not explained the reason to simplify the problem : I have a DataTable code that parse a json containing some information including a date. This date comes from a database (MySQL field type DATE) so it is in english format (e.g. yyyy-mm-dd), and I parse this date using Ìntl.DateTimeFormat to format it to the current locale of the user’s browser. But as the format may includes some characters that the plugin do not understand to sort this date column, I have to override the data-order property and put back the english formatted date. For the one that already tackled Datatable, I use dataSrc function callback to format the date, and rowCallback to try to alter the cells with the data-order attribute.

Answers:

How to create a Date() object from a unknown format using navigator.locale as the only hint for javascript ?

You can’t do that reliably. The browser language doesn’t define the format that a user might use.

If the format is unknown, the best you can do is guess (which is not recommended). Where users can enter a date as free text, you should specify the required format then validate that:

  1. It fits the required format
  2. It’s a valid date
  3. When parsed according to the required format, it represents the date that the user expected it to represent (e.g. parse it and show the resulting date in an unambiguous format like “24 January, 2017”)

Alternatively, provide UI controls that are unambiguous so the user selects the values, such as separate day, month and year controls or a calendar–style date selector.

Alternative, could we use Intl.DateTimeFormat to parse a date from a format using navigator.locale ?

No. The Intl.DateTimeFormat doesn’t define a parsing (input) format, only output format.

For some reason, the TC39 committee that maintains and updates ECMA-262 has virtually ignored the Date object for many years. It seriously needs a decent parser and formatter, the Intl object doesn’t assist with parsing and is unsuitable for formatting for most use cases, though it does have some good features.

There are plenty of good parsers and formatters in other languages and existing javascript libraries to base new parsing and formatting features on. They can also be introduced in a way that is easily patched by extending the Date or Date.prototype objects where support is lacking.

Questions:
Answers:

For the guys out there that could struggle with this, I came to a solution using some inspiration :

// Credit : https://stackoverflow.com/a/41751476/3753055

// From english/database to <your_language>
var database_date = new Date('2017-12-20');
var french_date = new Intl.DateTimeFormat().format(database_date);
console.log('french_date: ' + french_date);

// From <your_language> to english/database
var locale = window.navigator.userLanguage || window.navigator.language;
console.log('navigator language: ' + locale);

moment.locale(locale);

var localeData = moment.localeData();
var format = localeData.longDateFormat('L');
var database_date_retreived = moment(french_date, format).format('YYYY-MM-DD');

console.log('Result: ' + database_date_retreived);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment-with-locales.min.js"></script>

The trick is to use localeData to retrieve the formats information from the locale (hopefully moment.js understand alpha_2 country codes). With this snippet, you can virtually obtain any format of any country, and use moment to initialize a new date from a format (important). Then, it is easy to format to a desired format, here I want the typical database/english format yyyy-mm-dd.

Working with date and time
You just need to grab var formatTime = localeData.longDateFormat('LTS');, concatenate it with format variable with a space and you can retreive your datetime format.