Convert timestamp from timezone to UTC timestamp? - javascript

I am receiving a timestamp from a third-party API, that looks like: 1540388730994. However, I have been informed that this timestamp is in 'Europe/Amsterdam' timezone.
I need to convert this timestamp to UTC, as we store all our dates in UTC.
How is this possible in JavaScript?
So far I have tried:
const timestamp = 1540388730994
const timestampInUTC = moment.tz(timestamp, 'Europe/Amsterdam').utc().valueOf()
console.log(timestamp, timestampInUTC)
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.21/moment-timezone-with-data-2012-2022.min.js"></script>
However, you can clearly see that the two output timestamps are identical, whereas I would have expected the conversion to subtract 1-2 hours, as Amsterdam timezone is GMT+2.
What am I doing wrong here?

Timestamps in numeric form are always in UTC. If they've for some reason manually added/subtracted it by a time zone offset, they are doing it wrong. You don't see any change from moment, because a UTC timestamp is the same moment in time regardless of what time zone you represent the local time equivalent in. If you expected the timestamp to change, that would be representing an entirely different moment in time.

Related

constructing a date object along with time zone

I want to construct a Date object along with dynamically selected timezone. I am currently in IST time zone. I want to eliminate the usage of Date.parse() as it does not behave as expected at times.
let's assume tzOffset to be +05:30 for now. It could be any other timezone based on what users want. new Date(epochDate).toISOString(); converts the date to UTC timezone. How do I get the date in toISOString() format but also get it in the desired time zone
const tsConstruct = `${year}-${month}-${date}T${hour}:${min}:00${tzOffset}`;
const epochDate = Date.parse(tsConstruct);
scheduledTs = new Date(epochDate).toISOString();
JavaScript's Date does not store timezone info. It just stores the number of milliseconds from UNIX EPOCH. Then, depending if you use the UTC methods or not, it returns the date and time in UTC or the local time.
You should have to change the date and time, based on the timezone indicated, to UTC or local time, and then store it in a Date object. But, of course, to show the stored time in another timezone different to the local one or UTC, you must do the conversions yourself, so, as #RuChengChong suggested, use a helper library like momentjs.

How to compare dates with moment

I'm trying to compare dates from database (firebase) with NOW. I'm using moment.js and it's not working. I think it has something to do with the time zone (or UTC+01:00)...
Example.
date1: "2016-11-20T14:00:00"
NOW: "2016-11-20T14:49:20+01:00"
I get NOW with moment() and compare like this:
var date1 = moment("2016-11-20T14:00:00");
moment(date1).isSameOrAfter( moment() ) // returns true
The comparison is precisely one hour off... How can I fix this? AND: is there any best practice in storing and comparing dates across time zones.
Dates should always be saved in UTC. If you use string type the UTC date time value in ISO format.
So while saving convert from client time zone into UTC and while retrieving convert from UTC into client time zone.
Comparison should be done between two dates in the same time zone.
If the database value is in UTC and then you have to parse as .utc() while creating a moment object.
moment.utc("2016-11-20T14:00:00");
Change the NOW value to UTC before comparing.
moment.(date1).utc()
Alternatively you can change the database value from UTC to local.
moment.utc("2016-11-20T14:00:00").local()
Keep the NOW value as is before comparing.
You cannot compare the date you stored in Firebase with now() as it lacks the information about your timezone.
You can store dates using Firebase.ServerValue.TIMESTAMP
For Example:
date1: Firebase.ServerValue.TIMESTAMP
This will save your time in Unix Milliseconds (time since the Unix epoch, in milliseconds) by the Firebase Database servers.
Then you can compare with new Date().getTime() this will give your device time in Unix Milliseconds.
For Example:
if(new Date().getTime() >= date1) {
//do something
}
Hope it helps :)

.tz() in moment.js timezone does not convert time zones correctly

I am having trouble when converting from time zone to time zone using moment.js.
This is my code:
convertSelectedTimeZoneToClients() {
let timeZoneInfo = {
usersTimeZone: this.$rootScope.mtz.tz.guess(),
utcOffset: this.formData.timeZone.offset,
selectedDateTime: this.toJSONLocal(this.formData.sessionDate) + " " + this.formData.sessionTime
};
let utcTime = this.$rootScope.mtz.utc(timeZoneInfo.selectedDateTime).utcOffset(timeZoneInfo.utcOffset).format("YYYY-MM-DD HH:mm");
let con = this.$rootScope.mtz.tz(utcTime, timeZoneInfo.usersTimeZone).format();
return con;
}
The user picks date, time and time zone from drop downs on client page.
In timeZoneInfo object I am storing usersTimeZone (I want to be able to convert timezone that user selected on page and convert it to his local time zone).
For example user picks: 11/08/2016 01:30 and UTC+2 timezone and his timezone is UTC+1, than I want to show him in label: That is 11/08/2016 00:30 since UTC+1 is -1 hour comparing to UTC+2 timezone.
I store offsets for time zones in one object and those values are hard coded (utcOffset: this.formData.timeZone.offset).
Before I convert time form time zone to time zone I do this: get time zone -> convert to UTC time -> convert to user time zone.
What is happening is that utcTime variable has correct value. But when I pass that value and users time zone to .tz() function and using format() to get some readable value I get same time as utcTime like shown in picture:
I have read moment.js docs and by them this .tz().format() should do the work, but as you can see my result is: 2016-11-08T23:30:00+01:00.
So it gets that is should be incremented by 1 hour but how to accomplish to get: 2016-11-09T00:30 instead?
I have tried .format("YYYY-MM-DD HH:mm") as well same problem. When I use .local() function that should convert from utc time to specified time zone same problem is present.
Am I getting something wrongly? I am pretty sure that when you convert from 2016-11-08T23:30 UTC to UTC+1 it should be 2016-11-09T00:30, or one hour forward. Does someone sees something strange in this code?

How to display Datetime considering offset using MomentJS with Timezones

I'm using moment.js with timezones to create a datetime belonging to a specific timezone:
var datetime = moment.tz("2016-08-16 21:51:28","Europe/London");
Because this constructor is aware of DST (daylight saving time), moment.js will add +1 hour offset automatically. datetime.format() will show: 2016-08-16T21:51:28+01:00.
But it seems when printing the date, the offset ins't considered. E.g. datetime.format('DD.MM.YYYY - HH:mm:ss') will show: 16.08.2016 - 21:51:28 but I wan't it to show: 16.08.2016 - 22:51:28 (the time considering the DST-Offset of 1 hour). Does anyone know how to do this?
You are misinterpreting the output you're getting.
When you see +01:00 at the end of an ISO8601 timestamp, it doesn't mean that you need to add an hour. It means that timestamp given is in a local time zone that is one hour ahead of UTC at that point in time. Moment isn't adding an hour. It's simply reflecting the local time in London.
For the timestamps you provided, showing 22:51:28 would be an error. The local time in London is 21:51:28, and the equivalent UTC time is 20:51:28. You wouldn't find 22:51:28 until you went one time zone to the East, at UTC+2.
Now, if what you meant to do is convert from UTC to London time, then you need to create the input as UTC and then convert.
moment.utc("2016-08-16 21:51:28").tz("Europe/London")
Then you'd get 22:51:28 when formatting, which is the result you asked for, but this is a different point in time.

Moment.js local relative time

I have dates in my database set to Europe/London time. I am using Moment.js to show relative time e.g. "3 minutes ago". This works fine for me as I am in the same timezone, but for example, someone who is PST timezone would see "in 8 hours". How can I fix this?
My current code is like this:
$('time').text( moment( '2016-01-22 18:00:00' ).fromNow() );
To echo Jon's answer, moment's relative time functionality is strictly UTC based, so the behavior you describe won't actually happen, unless you are interpreting the original timestamp in local time.
It's hard to say if you're doing that or not, as you didn't give a sample value of the input string.
If your times are indeed UTC based, but that's not reflected in the input string, then use moment.utc instead of just moment.
And no, London is not the same as UTC.
I believe that the best approach is to store the date in UTC and then convert this to the local time zone for display. Note that this is not necessarily the same as London time because UTC does away with daylight savings time nonsense. You can do everything that you need with the date class provided the time stamp stored in the database does not have to deal with the vagaries of time zone and DST. The date class maintains its own epoch internally as milliseconds elapsed since midnight 1 January 1970 UTC. You can evaluate the difference between two Date objects as follows:
var agora = Date.now();
var stored = ... // the date that was stored in your database
var diff_msec = agora.getTime() - stored.getTime();
Knowing that the difference and that its units are milliseconds, you can convert the difference to whatever units are best for presentation.

Categories