moment-timezone
moment-timezone copied to clipboard
moment.tz(timezone, keepTime=true) doesn't keep time for days of DST switch
Could somebody explain the next behaviour:
I have a UTC time. Let's say 2018-11-02T05:00:00.000Z
. And I want to change the timezone to America/Los_Angeles
, but keep the 2018-11-02T05:00:00.000
part. Looks like moment('2018-11-02T05:00:00.000Z').tz('America/Los_Angeles', true)
is a solution for this task. But for days and timezones when there is a DST/STD transition it produces strange results (for example for 4th of November in this timezone it gives me 4 AM instead of 5AM local time).
// run.js
const moment = require('moment-timezone');
const tz = 'America/Los_Angeles';
const t1 = moment('2018-11-02T05:00:00.000Z');
console.log(t1.format(), moment(t1).tz(tz, true).format(), moment(t1).tz(tz, true).toISOString());
const t2 = moment('2018-11-03T05:00:00.000Z');
console.log(t2.format(), moment(t2).tz(tz, true).format(), moment(t2).tz(tz, true).toISOString());
const t3 = moment('2018-11-04T05:00:00.000Z');
console.log(t3.format(), moment(t3).tz(tz, true).format(), moment(t3).tz(tz, true).toISOString());
const t4 = moment('2018-11-05T05:00:00.000Z');
console.log(t4.format(), moment(t4).tz(tz, true).format(), moment(t4).tz(tz, true).toISOString());
$ TZ=UTC node run.js
2018-11-02T05:00:00+00:00 2018-11-02T05:00:00-07:00 2018-11-02T12:00:00.000Z
2018-11-03T05:00:00+00:00 2018-11-03T05:00:00-07:00 2018-11-03T12:00:00.000Z
2018-11-04T05:00:00+00:00 2018-11-04T04:00:00-08:00 2018-11-04T12:00:00.000Z // !!! 4 instead of 5
2018-11-05T05:00:00+00:00 2018-11-05T05:00:00-08:00 2018-11-05T13:00:00.000Z
At the same time if I change the time to 2018-11-03T10:00:00.000Z
everything works as expected. I suspect because the DST/STD happens at 9AM UTC.
node version: v8.7.0
moment version: 2.22.2
moment-timezone version: 0.5.21
I experience the same issue
@Ostrovski do you use somewhere in the code something like this moment.tz.setDefault(timezone);
?
@navasiloy no, I don't use this function. The minimal code to reproduce the problem one can find in the original issue.
I've also experienced the same issue. Here's what I've discovered.
Let's say that the local machine is running on the Europe/London timezone. If we happen to convert a time in America/Chicago on the day of daylight savings time (Clock moves forward an hour on 2019-03-10T02:00:00.000), there will be a five hour window (from 3 to 8) where
console.log(moment('2019-03-10T03:00:00.000').tz('America/Chicago', true).toJSON());
will convert the time to UTC using a six hour offset instead of a five hour offset.
However, if my local timezone is in America/Chicago,
console.log(moment('2019-03-10T03:00:00.000').tz('America/Chicago', true).toJSON());
will convert the time to UTC with the correct offset.
An easy way to recreate this is the following:
Wrong UTC time
moment.tz.setDefault('Europe/London'); console.log(moment('2019-03-10T07:00:00.000').tz('America/Chicago', true).toJSON());
Correct UTC time
moment.tz.setDefault('America/Chicago'); console.log(moment('2019-03-10T07:00:00.000').tz('America/Chicago', true).toJSON());
Is there any solution to this issue?
I hope the solution below helps @raliasadil. My scenario for the solution is a bit strange. Basically I had users who wanted to select a time and a timezone and have that be the date for a change to occur to a system. For example, they wanted a change to occur at 12:00 in America/Chicago time but they were in London. The API was in UTC.
const selectedTimeZone = 'America/Chicago';
const localTimeZone = moment.tz.guess();
moment.tz.setDefault(selectedTimeZone);
const effectiveDate = moment('2019-03-10T07:00:00.000').tz(selectedTimeZone, true).toJSON();
moment.tz.setDefault(localTimeZone);
console.log(effectiveDate);
At this point I'd recommended using Luxon. Unfortunately on UI projects, a lot of UI components use moment as a first class citizen. The shift to Luxon will take a couple years.
Same issue here. "Fixed" with the moment.tz.setDefault(userTimezone) workaround...
My scenario :
1- User can choose the starting hour of his working day
2- I use the below code to retrieve current day and starting at the moment chosen by user
const startfulldate = moment()
.hour(startHourChosenByUser)
.minute(startMinuteChosenByUser)
.second(0)
.millisecond(0)
.tz(userTimezone, true)
.toDate();
3- Code was giving a wrong time (+1 hour) on next DST days (29th March 2020 for France)
4- Fixed by adding the setDefault() function above code
moment.tz.setDefault(userTimezone)
We are facing this exact issue in our project
Here is a workaround we ended up using:
moment.tz(momentDate.format('YYYY-MM-DDTHH:mm:ss'), tz)
this is basically the equivalent of doing momentDate.tz(tz, true)
, but it is not affected by the bug
Note: this workaround doesn't keep milliseconds - if required to keep that as well - .format pattern should be extended
It's Daylight Savings Time again, and I believe I'm hitting this bug. I assume we didn't hit this bug last year because of what someone else said earlier:
there will be a five hour window (from 3 to 8) where [the library] will convert the time to UTC using a six hour offset instead of a five hour offset.
and we didn't happen to observe the behavior before 08:00...