Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

moment.utc(string) parses ISO8601 as local time when timezone is missing #275

Closed
timrwood opened this issue Apr 12, 2012 · 24 comments
Closed

moment.utc(string) parses ISO8601 as local time when timezone is missing #275

timrwood opened this issue Apr 12, 2012 · 24 comments
Assignees
Labels

Comments

@timrwood
Copy link
Member

@timrwood timrwood commented Apr 12, 2012

See this comment: #272 (comment)

@ghost ghost assigned timrwood Apr 12, 2012
@Yaffle
Copy link

@Yaffle Yaffle commented Apr 15, 2012

moment.utc(string) parses ISO8601 as local time when timezone is missing

this is how ISO8601 says... and EcmaScript 6

@timrwood
Copy link
Member Author

@timrwood timrwood commented Apr 16, 2012

I think that applies to moment(string) pretty well, but when using moment.utc(string), I think the implication is that you want it parsed as UTC.

moment('2010-10-20T08:40'); // should parse to local time
moment.utc('2010-10-20T08:40'); // should parse to utc time
@raulferras
Copy link

@raulferras raulferras commented Apr 17, 2012

I'm having an issue, I think related with this:

I'm trying to convert this date: 12-04-2012 (DD-MM-YYYY, in UTC) to its Unix timestamp.
I'm doing this:

var date = '12-04-2012';
var mm = moment().utc( date, "DD-MM-YYYY" );
console.log( mm.valueOf() );

This outputs an incorrect timestamp: 1334670827391.
If I try:

console.log( mm.format('DD-MM-YYYY') );

It outpus: 17-04-2012

@timrwood
Copy link
Member Author

@timrwood timrwood commented Apr 25, 2012

a538306 fixes this. Will go out in 1.6.0

@timrwood timrwood closed this Apr 25, 2012
@niemyjski
Copy link

@niemyjski niemyjski commented Jan 16, 2013

I'm still seeing this issue in the latest version..

I'm passing in: moment.utc('2012-12-14T00:29:40.276Z') and getting: {_d: Thu Dec 13 2012 18:29:40 GMT-0600 (Central Standard Time), _isUTC: true (Thu Dec 13 2012 18:29:40 GMT-0600 (Central Standard Time) ).. It's not using the utc time but my local timezone.

@timrwood
Copy link
Member Author

@timrwood timrwood commented Jan 16, 2013

This is what I'm getting with 1.7.2.

moment.utc('2012-12-14T00:29:40.276Z').format(); // "2012-12-14T00:29:40+00:00"
@niemyjski
Copy link

@niemyjski niemyjski commented Jan 16, 2013

Here is what happens for me (latest version) when I write to the console in chrome:

console.log(moment.utc('2012-12-14T00:29:40.276Z'));
console.log(moment.utc('2012-12-14T00:29:40.276Z').format());
console.log(moment.utc('2012-12-14T00:29:40.276Z').toDate());

H {_d: Thu Dec 13 2012 18:29:40 GMT-0600 (Central Standard Time), _isUTC: true, _a: Array[8], _lang: false, clone: function…}

2012-12-14T00:29:40+00:00

Thu Dec 13 2012 18:29:40 GMT-0600 (Central Standard Time)

Shouldn't it be creating a new date in utc (no time zone)? Also the first console.log shows the moment object with a cst timezone and not it's utc time.

@timrwood
Copy link
Member Author

@timrwood timrwood commented Jan 16, 2013

Thu Dec 13 2012 18:29:40 GMT-0600 is actually the exact same time as 2012-12-14T00:29:40.276Z. They are just different ways of displaying the same time. If you want, you can see this by doing the following.

console.log(moment.utc('2012-12-14T00:29:40.276Z').toDate().toString());
// Thu Dec 13 2012 16:29:40 GMT-0800 (PST)
console.log(moment.utc('2012-12-14T00:29:40.276Z').toDate().toUTCString());
// Fri, 14 Dec 2012 00:29:40 GMT

The native JS Date does not have a utc vs local mode, it just has accessors like getUTCHours and getHours.

Moment.js abstracts these getUTC* vs get* methods with the idea of utc mode and local mode. If the moment is in utc mode, it uses the getUTC* methods. If it is in local mode, it uses the get* methods.

@niemyjski
Copy link

@niemyjski niemyjski commented Jan 16, 2013

Thanks, for the clarification.

I was expecting and thought that sinze the iso standard states that Z means no timezone that it would default to utc. So if you did moment.utc('2012-12-14T00:29:40.276Z') or moment('2012-12-14T00:29:40.276Z'), both would be treated as utc and the utc flag would be set to true.

P.S., sorry for bothering you so much :. I'm creating a new discussion for a different question :s

@timrwood
Copy link
Member Author

@timrwood timrwood commented Jan 16, 2013

No problem.

The reason we don't set the isUTC flag with both moment() and moment.utc() is because even though you may be parsing a UTC+0 string, you may want to display the moment in the users timezone.

This is a pretty common use case, as it's a good practice to store times as ISO8601 UTC+0 strings on the backend and display them on the frontend in the user's timezone.

@niemyjski
Copy link

@niemyjski niemyjski commented Jan 16, 2013

Thanks, I hope someone else finds this discussion helpful too.

@tylercloke
Copy link

@tylercloke tylercloke commented Jan 19, 2013

When I run console.log(moment.utc()), it reports "Fri Jan 18 2013 16:25:32 GMT-0800 (UTC)" However, that is local Pacific time, NOT the current UTC time. Since it explisitly says (UTC) when I log it, I assume that it thinks "16:25:32" is in UTC time, but it is indeed local pacific time...

Additionally, I am assuming moment.utc().valueOf() is returning the number of milliseconds in UTC since epoch, which appears to be incorrect. Have you seen any of this behavior?

@tylercloke
Copy link

@tylercloke tylercloke commented Jan 19, 2013

console.log(moment())
H {_d: Fri Jan 18 2013 16:51:20 GMT-0800 (UTC), _isUTC: false, _a: null, _lang: false}
console.log(moment.utc())
H {_d: Fri Jan 18 2013 16:51:20 GMT-0800 (UTC), _isUTC: true, _a: null, _lang: false}

It would appear all that it is doing is flipping the _isUTC flag. :P It appears to be returning local time regardless of whether or not I specify .utc().

@timrwood
Copy link
Member Author

@timrwood timrwood commented Jan 23, 2013

Yes, .utc and .local just flip the .isUTC flag which is used in all the getters and setters.

Because the native Date.toString is displayed in local time, you are seeing the same representation in both instances.

However, .format uses the .isUTC flag, so formatting a moment with the isUTC flag set to true will format as expected.

See the differences below regarding Date.prototype.toString, Date.prototype.toUTCString, and moment.fn.format.

moment().toDate().toString();     // "Wed Jan 23 2013 09:48:54 GMT-0800 (PST)"
moment.utc().toDate().toString(); // "Wed Jan 23 2013 09:48:54 GMT-0800 (PST)"
moment().toDate().toUTCString();     // "Wed, 23 Jan 2013 17:48:54 GMT"
moment.utc().toDate().toUTCString(); // "Wed, 23 Jan 2013 17:48:54 GMT"
moment().format();     // "2013-01-23T09:48:54-08:00"
moment.utc().format(); // "2013-01-23T17:48:54+00:00"
@rubenspgcavalcante
Copy link

@rubenspgcavalcante rubenspgcavalcante commented Jul 3, 2015

Same problem here:
moment().valueOf() and moment().utc().valueOf()
return the same value! 😞

So to get the utc milliseconds I need to:

moment().valueOf() - (moment().utcOffset() * 60 * 1000)
@mattjohnsonpint
Copy link
Member

@mattjohnsonpint mattjohnsonpint commented Jul 4, 2015

@rubenspgcavalcante - I'm not sure what you're asking. Those two are supposed to return the same value, both of which are in milliseconds since the unix epoch.

The snippet you wrote actually returns a different moment in time.

@jamesh38
Copy link

@jamesh38 jamesh38 commented Jul 10, 2016

I'm having similar issue where the UTC flag is set to true but when I cal format(); It returns the local time. Here is a screenshot.

screen shot 2016-07-10 at 8 50 15 am

The line after the object is a console.log of the var after I call format(); on it.

Am I doing something wrong?

@maggiepint
Copy link
Member

@maggiepint maggiepint commented Jul 10, 2016

@james-hoegerl it looks like the internal date object is July 5 2016 at 19:00 central. Add five hours to that to get to UTC, and it is July 6, which is what appears to be logging, so in short, I don't see anything wrong.
It does look like you're using fullcalendar. It does some extension/monkey patching of moment that may cause unusual behavior.

@jamesh38
Copy link

@jamesh38 jamesh38 commented Jul 10, 2016

Ok maybe I'm just confused about uct. I thought I would get "2016-05-07 07:00:00" then I could store that in the DB and then get local time for each end user computer via moment.

@maggiepint
Copy link
Member

@maggiepint maggiepint commented Jul 11, 2016

So, first of all I will assume you meant 6016-07-05 (July 5th, not May 7th). Your local time is July 5th at 19:00. Adjusted for US Central Daylight, we add five hours. That yields July 6th at midnight.

If you mean to get July 5th, then I think what you actually want is local time, not UTC. You could call .local() on the moment to get it back to local time.

You may find this helpful: https://maggiepint.com/2016/05/14/moment-js-shows-the-wrong-date/

@jamesh38
Copy link

@jamesh38 jamesh38 commented Jul 11, 2016

Thanks very much for your help @maggiepint. Yes my previous comment I did mean 7-5. Sorry about that I wrote that comment hastily on my phone by the pool this weekend. I see where my thinking has been backwards now. fullcalendar works on all ambiguous time zoned moment objects so I think I was just having some misunderstanding there and need to do some sutdying on that. Thanks again for your time @maggiepint

@swetha21
Copy link

@swetha21 swetha21 commented May 29, 2018

Hi, To convert UTC to user time, do we need to provide format.
for example : let utcTime = moment({ hour : 10, minute : 20).format('YYYY-MM-DD HH:mm:ss');
let stillUtc = moment.utc(utcTime).toDate();
let localTime = moment(stillUtc).local();
Now i can able to get localTIme. But if i remove format i can still UTC format . here 10:20 is UTC timeZone which is coming from backend. I want to show this to user in user timezone.

Please help me.

@beebase
Copy link

@beebase beebase commented Jun 11, 2018

Same problem here:
moment().valueOf() and moment().utc().valueOf()
return the same value! 😞
So to get the utc milliseconds I need to:
moment().valueOf() - (moment().utcOffset() * 60 * 1000)

@rubenspgcavalcante - I'm not sure what you're asking. Those two are supposed to return the same value, both of which are in milliseconds since the unix epoch.

@mj1856 I don't understand how moment().valueOf() and moment().utc().valueOf() are supposed to return the same value ??

@bearoutthere
Copy link

@bearoutthere bearoutthere commented Oct 13, 2018

I must add to the expression of confusion around the UTC functionality. The most intuitive expectation of moment.utc() would be that it would return a Moment object representing the now date/time in UTC time. But according to this discussion it's not the case and it just sets the flag. It still unclear what that flag does. None of this is mentioned in the documentation, which makes it woefully inadequate. Please add clarification of this topic with examples to your backlog. Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet