brg
brg

Reputation: 3953

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?

Upvotes: 129

Views: 296209

Answers (4)

Ann lopez
Ann lopez

Reputation: 1

none of the above worked for me❌. I tried converting the date using moment()utc, use parseZone, but none of them worked.

✅Converting the date to ISO string using javascript's toISOString() did though ✅

// input date is "2023-09-28T00:00:00-05:00" 
// timezone is chicago time GMT-5:00
const date_str =  new Date(this.date); 

const isoDate =  date_str.toISOString(); 
// isoDate Result "2023-09-28T05:00:00.000Z"


// Before i used the isoString method,  moment() would
//  would always get the previous date
 
const startTime = moment(isoDate)
    .set('hour', parseInt(momentConfigStartTimeOfDay.hour))
    .set('minute', parseInt(momentConfigStartTimeOfDay.minute))
    .format();
const endTime = moment(isoDate)
    .set('hour', parseInt(momentConfigEndTimeOfDay.hour))
    .set('minute', parseInt(momentConfigEndTimeOfDay.minute))
    .format();
Hopefully this helps someone. I've spent more than a day trying to figure out what would work haha

Upvotes: 0

Mohammad Sbaih
Mohammad Sbaih

Reputation: 31

use this :

return moment.utc(new Date(oData.CreatedAtUtc), 'MM/DD/YYYY h:mm A').local().format("YYYY-MM-DD HH:mm") + ' (' + timezoneAbbr + ')';

Upvotes: 2

MasterAM
MasterAM

Reputation: 16488

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"

Upvotes: 211

Matt Johnson-Pint
Matt Johnson-Pint

Reputation: 241920

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.

Upvotes: 41

Related Questions