Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

moment.js - UTC gives wrong date

Why does moment.js UTC always show the wrong date. For example from chrome's developer console:

moment(('07-18-2013')).utc().format("YYYY-MM-DD").toString() // or moment.utc(new Date('07-18-2013')).format("YYYY-MM-DD").toString() 

Both of them will return "2013-07-17" why is it returning 17th instead of 18th, that was passed in.

But if I use momentjs without the utc:

moment(new Date('07-18-2013')).format("YYYY-MM-DD").toString() 

I get back "2013-07-18" which is what I also expect when using moment.js UTC.

Does this mean we cannot get the correct date when using moment.js UTC?

like image 511
brg Avatar asked Jul 25 '13 10:07

brg


People also ask

Does moment use UTC?

utc(Date); By default, moment parses and displays in local time. If you want to parse or display a moment in UTC, you can use moment.

Why you shouldnt use MomentJS?

However, Moment. js has too many drawbacks compared to modern date and time libraries. Its API is not immutable, it is large and it doesn't support tree shaking. Even the Moment team discourages to use their library in new projects.

Does moment convert UTC to local?

To convert UTC time to Local you have to use moment. local() .


2 Answers

By default, MomentJS parses in local time. If only a date string (with no time) is provided, the time defaults to midnight.

In your code, you create a local date and then convert it to the UTC timezone (in fact, it makes the moment instance switch to UTC mode), so when it is formatted, it is shifted (depending on your local time) forward or backwards.

If the local timezone is UTC+N (N being a positive number), and you parse a date-only string, you will get the previous date.

Here are some examples to illustrate it (my local time offset is UTC+3 during DST):

>>> moment('07-18-2013', 'MM-DD-YYYY').utc().format("YYYY-MM-DD HH:mm") "2013-07-17 21:00" >>> moment('07-18-2013 12:00', 'MM-DD-YYYY HH:mm').utc().format("YYYY-MM-DD HH:mm") "2013-07-18 09:00" >>> Date() "Thu Jul 25 2013 14:28:45 GMT+0300 (Jerusalem Daylight Time)" 

If you want the date-time string interpreted as UTC, you should be explicit about it:

>>> moment(new Date('07-18-2013 UTC')).utc().format("YYYY-MM-DD HH:mm") "2013-07-18 00:00" 

or, as Matt Johnson mentions in his answer, you can (and probably should) parse it as a UTC date in the first place using moment.utc() and include the format string as a second argument to prevent ambiguity.

>>> moment.utc('07-18-2013', 'MM-DD-YYYY').format("YYYY-MM-DD HH:mm") "2013-07-18 00:00" 

To go the other way around and convert a UTC date to a local date, you can use the local() method, as follows:

>>> moment.utc('07-18-2013', 'MM-DD-YYYY').local().format("YYYY-MM-DD HH:mm") "2013-07-18 03:00" 
like image 165
MasterAM Avatar answered Sep 20 '22 09:09

MasterAM


Both Date and moment will parse the input string in the local time zone of the browser by default. However Date is sometimes inconsistent with this regard. If the string is specifically YYYY-MM-DD, using hyphens, or if it is YYYY-MM-DD HH:mm:ss, it will interpret it as local time. Unlike Date, moment will always be consistent about how it parses.

The correct way to parse an input moment as UTC in the format you provided would be like this:

moment.utc('07-18-2013', 'MM-DD-YYYY') 

Refer to this documentation.

If you want to then format it differently for output, you would do this:

moment.utc('07-18-2013', 'MM-DD-YYYY').format('YYYY-MM-DD') 

You do not need to call toString explicitly.

Note that it is very important to provide the input format. Without it, a date like 01-04-2013 might get processed as either Jan 4th or Apr 1st, depending on the culture settings of the browser.

like image 33
Matt Johnson-Pint Avatar answered Sep 23 '22 09:09

Matt Johnson-Pint