samsonjs/strftime

Problem with DST and UTC

ray007 opened this issue · 5 comments

I'm using strftime to create timelabel along a chart axis, and a customer noticed a glitch with the last DST change.
To test I dumped the dates around the DST change, the formatted string ("%F %T") for utc and the timezone offset onto the console and got this:

Sun Oct 30 2016 02:50:00 GMT+0200 (W. Europe Daylight Time) "2016-10-30 00:50:00" -120
Sun Oct 30 2016 02:00:00 GMT+0100 (W. Europe Standard Time) "2016-10-30 02:00:00" -60
Sun Oct 30 2016 02:10:00 GMT+0100 (W. Europe Standard Time) "2016-10-30 02:10:00" -60
Sun Oct 30 2016 02:20:00 GMT+0100 (W. Europe Standard Time) "2016-10-30 02:20:00" -60
Sun Oct 30 2016 02:30:00 GMT+0100 (W. Europe Standard Time) "2016-10-30 02:30:00" -60
Sun Oct 30 2016 02:40:00 GMT+0100 (W. Europe Standard Time) "2016-10-30 02:40:00" -60
Sun Oct 30 2016 02:50:00 GMT+0100 (W. Europe Standard Time) "2016-10-30 02:50:00" -60
Sun Oct 30 2016 03:00:00 GMT+0100 (W. Europe Standard Time) "2016-10-30 02:00:00" -60
Sun Oct 30 2016 03:10:00 GMT+0100 (W. Europe Standard Time) "2016-10-30 02:10:00" -60

If you're in the US, I assume you need to check with dates one week later.

Note: inverting the date-manipulation dependent on _useUtcBasedDate in _strftime() and using the getUTC* methods in _processFormat() seems to make the problem go away...

Since nobody else seems interested, see #73

@ray007 How are you creating those dates? Can you share that code so I can test things out? It seems to work as expected here when creating dates using timestamps with the timezone Europe/Amsterdam. I also tried using WET and it works as expected but all times are an hour earlier.

test-dst.js:

#!/usr/bin/env node
var strftime = require('./strftime.js');
var start = 1477782000 * 1000; // 2016-10-30 01:00:00 +0200 (Europe/Amsterdam)
var tenMinutes = 10 * 60 * 1000;
for (var i = 0; i < 18; i++) {
    var t = start + (i * tenMinutes);
    console.log('strftime("%F %T %z", ' + t + ') = ' + strftime('%F %T %z', new Date(t)));
}

Result:

$ TZ=Europe/Amsterdam ./test-dst.js
strftime("%F %T %z", 1477782000000) = 2016-10-30 01:00:00 +0200
strftime("%F %T %z", 1477782600000) = 2016-10-30 01:10:00 +0200
strftime("%F %T %z", 1477783200000) = 2016-10-30 01:20:00 +0200
strftime("%F %T %z", 1477783800000) = 2016-10-30 01:30:00 +0200
strftime("%F %T %z", 1477784400000) = 2016-10-30 01:40:00 +0200
strftime("%F %T %z", 1477785000000) = 2016-10-30 01:50:00 +0200
strftime("%F %T %z", 1477785600000) = 2016-10-30 02:00:00 +0200
strftime("%F %T %z", 1477786200000) = 2016-10-30 02:10:00 +0200
strftime("%F %T %z", 1477786800000) = 2016-10-30 02:20:00 +0200
strftime("%F %T %z", 1477787400000) = 2016-10-30 02:30:00 +0200
strftime("%F %T %z", 1477788000000) = 2016-10-30 02:40:00 +0200
strftime("%F %T %z", 1477788600000) = 2016-10-30 02:50:00 +0200
strftime("%F %T %z", 1477789200000) = 2016-10-30 02:00:00 +0100
strftime("%F %T %z", 1477789800000) = 2016-10-30 02:10:00 +0100
strftime("%F %T %z", 1477790400000) = 2016-10-30 02:20:00 +0100
strftime("%F %T %z", 1477791000000) = 2016-10-30 02:30:00 +0100
strftime("%F %T %z", 1477791600000) = 2016-10-30 02:40:00 +0100
strftime("%F %T %z", 1477792200000) = 2016-10-30 02:50:00 +0100

My test-dst.js looks like this:

#!/usr/bin/env node
var strftime = require('./strftime.js'), su = strftime.utc();
var start = new Date("2016-10-30 02:30:00");
var tenMinutes = 10 * 60 * 1000, fmt = '%F %T %z';
for (var i = 0; i < 18; i++) {
    var t = new Date(+start + (i * tenMinutes));
    console.log(t, strftime(fmt, t), su(fmt, t), t.getTimezoneOffset());
}

Looking at this I see I'm missing an adjustment for the timezone formatter, will take a look at that in a moment.

EDIT: I've pushed a fix for "%z", there might still be something missing for "%Z". Also not tested with foreign timezones.

Thanks for the extra info @ray007, I had missed that you said "UTC" in your initial message here. Should be all fixed on master now. Really good catch here. Subtle bug.