MomentJS getting JavaScript Date in UTC
Asked Answered
T

5

86

I am not able to get the JavaScript Date string for MongoDB record via the following. It keeps using my local time.

var utc = moment.utc().valueOf();
console.log(moment.utc(utc).toDate());

Output:

Tue Nov 11 2014 14:42:51 GMT-0500 (EST)

I need it to be in UTC, so I can stick this timestamp in Mongo so type would be Date.

How can I do that?

Timbered answered 11/11, 2014 at 19:45 Comment(13)
What breaks when you store the date object as is?Incunabulum
it gets stored as a double, not a Date type object. I need it to be toDate() of utc. having a horrible time with this. thanks for help!Timbered
I ask again, what breaks when you store it as is. Does it load incorrect dates? Does it break in different time zones?Incunabulum
why the hell cant i just do this: var now = moment.utc().toDate(); and store that :(Timbered
not sure what you mean by as isTimbered
beacuse it goes in as a double into mongo, i want it to be of type DateTimbered
Your missing my point. Is there no way to deal with the double? Is the double not valid?Incunabulum
I understood you quite well. Must be of Date native Javascript object typeTimbered
Mongo uses BSON. It's got to convert JS objects into compatible storage types. if you're using mongo wrong you're probably going to have to convert dates back into date objects yourself.Incunabulum
so whats the answer to my original question? :)Timbered
the toDate() funciton seems to convert everything to local timezoneTimbered
Try new Date(moment.utc().toDate())Secund
Take a look at github.com/moment/moment-timezone/issues/…Glen
R
115

A timestamp is a point in time. Typically this can be represented by a number of milliseconds past an epoc (the Unix Epoc of Jan 1 1970 12AM UTC). The format of that point in time depends on the time zone. While it is the same point in time, the "hours value" is not the same among time zones and one must take into account the offset from the UTC.

Here's some code to illustrate. A point is time is captured in three different ways.

var moment = require( 'moment' );

var localDate = new Date();
var localMoment = moment();
var utcMoment = moment.utc();
var utcDate = new Date( utcMoment.format() );

//These are all the same
console.log( 'localData unix = ' + localDate.valueOf() );
console.log( 'localMoment unix = ' + localMoment.valueOf() );
console.log( 'utcMoment unix = ' + utcMoment.valueOf() );

//These formats are different
console.log( 'localDate = ' + localDate );
console.log( 'localMoment string = ' + localMoment.format() );
console.log( 'utcMoment string = ' + utcMoment.format() );
console.log( 'utcDate  = ' + utcDate );

//One to show conversion
console.log( 'localDate as UTC format = ' + moment.utc( localDate ).format() );
console.log( 'localDate as UTC unix = ' + moment.utc( localDate ).valueOf() );

Which outputs this:

localData unix = 1415806206570
localMoment unix = 1415806206570
utcMoment unix = 1415806206570
localDate = Wed Nov 12 2014 10:30:06 GMT-0500 (EST)
localMoment string = 2014-11-12T10:30:06-05:00
utcMoment string = 2014-11-12T15:30:06+00:00
utcDate  = Wed Nov 12 2014 10:30:06 GMT-0500 (EST)
localDate as UTC format = 2014-11-12T15:30:06+00:00
localDate as UTC unix = 1415806206570

In terms of milliseconds, each are the same. It is the exact same point in time (though in some runs, the later millisecond is one higher).

As far as format, each can be represented in a particular timezone. And the formatting of that timezone'd string looks different, for the exact same point in time!

Are you going to compare these time values? Just convert to milliseconds. One value of milliseconds is always less than, equal to or greater than another millisecond value.

Do you want to compare specific 'hour' or 'day' values and worried they "came from" different timezones? Convert to UTC first using moment.utc( existingDate ), and then do operations. Examples of those conversions, when coming out of the DB, are the last console.log calls in the example.

Ramshackle answered 12/11, 2014 at 15:32 Comment(4)
I think your are missing the essence of the question.Deroo
I answered this way because his question showed the use of MomentJS. The idea was that a timestamp (the numbers) is the real value, and the date format (the words) is often dependent on the local time zone.Ramshackle
new Date(moment.utc().format()) does not return UTC date. "Note: It's important to keep in mind that while the time value at the heart of a Date object is UTC, the basic methods to fetch the date and time or its components all work in the local (i.e. host system) time zone and offset." from developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Glen
@PouriaMoosavi Absolutely right. I don't understand how this answer has so many upvotes. It contains incorrect and confusing information. Whenever you wrap any date in new Date(), it will always return in host timezone.Kaki
D
10

Calling toDate will create a copy (the documentation is down-right wrong about it not being a copy), of the underlying JS Date object. JS Date object is stored in UTC and will always print to eastern time. Without getting into whether .utc() modifies the underlying object that moment wraps use the code below.

You don't need moment for this.

new Date().getTime()

This works, because JS Date at its core is in UTC from the Unix Epoch. It's extraordinarily confusing and I believe a big flaw in the interface to mix local and UTC times like this with no descriptions in the methods.

Deroo answered 27/9, 2016 at 22:59 Comment(0)
I
2

When you call .utc(), all you're doing is setting a flag in the Moment object that says "this must format as UTC." You can see this change if you inspect the object's properties.

As another answer mentioned, the point in time remains the same. This ensures calculations etc. can be carried out without worrying about the time zone.

A JavaScript Date also stores timezone information, and similarly will format the value it represents as local or UTC depending on what method you call.

Option 1

Use the formatting methods as they were intended, and make the last thing you do before sending the value to the server a format into a UTC string.

For Moment, that's simply calling .toISOString() on any date local or otherwise, or the .format() method after calling .utc() if you want to specify a different format.

For JS dates, that's also a .toISOString() method.

If for some reason you don't have the ability to keep the dates in local time, or can't transform to a string for the data send, you have (at least) two further options:

Option 2

Use the JS Date constructor to manually create a datetime in the local timezone, pulling the components from your UTC Moment object.

let utc = moment().utc();
let date = new Date(utc.year(), utc.month(), utc.date(), utc.hour(), utc.minute(), utc.second(), utc.millisecond());

Alternatively, get the current datetime and then set the hours and minutes as appropriate for the timezone change.

You'll end up with a date representation of the UTC time marked as local time. This is not the correct time, as you're now offset by the time zone, but it might solve a problem in a pinch.

Option 3

Similar to option 2, this is another way to create an offset Date where UTC is marked as the local time zone.

Export the ISO string from either Moment or JS, strip off the Zulu flag at the end, and use the string constructor for Date to pull it back in.

new Date(new Date().toISOString().slice(0,-1));

Again, this is not actually the correct time and calculations against other datetimes may be incorrect. Your best option is still to send up a UTC ISO string to the server when you can.

Iroquois answered 28/6, 2022 at 15:2 Comment(0)
S
1

This will give you the UTC timezone DateTime.

var convertedUtcDateTime = moment.utc(dateTimeToBeConverted);
Snoddy answered 5/5, 2021 at 8:36 Comment(0)
R
-1

Or simply:

Date.now

From MDN documentation:

The Date.now() method returns the number of milliseconds elapsed since January 1, 1970

Available since ECMAScript 5.1

It's the same as was mentioned above (new Date().getTime()), but more shortcutted version.

Remitter answered 25/7, 2019 at 4:13 Comment(2)
That's unix time which isn't quite the same as UTC time.Diadromous
This is wrong! Works only if machine timezone is UTCNesmith

© 2022 - 2024 — McMap. All rights reserved.