Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript parse date from toLocaleDateString for known locale

Background

In my application I want to format dates according to the user's locale. If the user modifies the date, I want to be able to parse it back into a javascript Date object.

Problem

I wonder if it's possible to parse a date from a locally formatted string using javascript?

Please consider the following snippet:

new Date(2016, 0, 1).toLocaleDateString('ar');
>>"١‏/١‏/٢٠١٦"

If I want to parse that string back to a valid date how would I go about that?

The following will not work:

new Date(new Date(2016, 0, 1).toLocaleDateString('ar'));
>>Invalid Date

I also experimented with using momentjs but was unable to find a working way there.

//change global locale
moment.locale('ar-sa');

moment().format('L');
>>"١٥/٠٦/٢٠١٦"

moment(new moment().format('L'))._d;
>>Invalid Date

Or is there some other/better way to think around issues like this?

like image 914
JesperA Avatar asked Jun 15 '16 10:06

JesperA


1 Answers

Because of the way JS Date works, there really isn't a good way to do this with just the Date object. It doesn't have consistent parsing behavior.

Moment will do this for you, and you're actually quite close. I'm not sure why you're calling the new keyword on moment. That isn't necessary. To get an Arabic date with Moment:

moment.locale('ar-sa'); 
moment().format('L')
"١٥/٠٦/٢٠١٦"

To parse that date back into a moment:

moment("١٥/٠٦/٢٠١٦", 'L').format()
"٢٠١٦-٠٦-١٥T٠٠:٠٠:٠٠-٠٥:٠٠"

Or if you want English characters for interacting with an API:

moment("١٥/٠٦/٢٠١٦", 'L').locale('en').format()
"2016-06-15T00:00:00-05:00"

Note that when you use 'L' you are telling moment that you are specifically looking for the date format 'DD/MM/YYYY'. For reference, the Arabic Saudi Arabia localized date formats are as follows:

    LT : 'HH:mm',
    LTS : 'HH:mm:ss',
    L : 'DD/MM/YYYY',
    LL : 'D MMMM YYYY',
    LLL : 'D MMMM YYYY HH:mm',
    LLLL : 'dddd D MMMM YYYY HH:mm'

As such, whatever format you use as the second parameter to moment will be the format moment is looking for. Different locales have different formats, so you need to be careful when changing between locales.

If you need to get back to a date object, you can do the following:

moment("١٥/٠٦/٢٠١٦", 'L').toDate()

I must warn you though, this is not best practice in Moment.js unless you have a third party API that needs to consume a date. Moment is a complete API (and a better one than JS Date), so any code you need to write related to date and time manipulation is better done within the moment ecosystem.

like image 116
Maggie Pint Avatar answered Oct 12 '22 13:10

Maggie Pint