UTC time convert error (and temporary solving method)
UTC time convert cause a wrong time offset here is the problem, when I use dayjs convert a time that just in the daylight saving time converting period, it will cause the time offset equal to +(X-1):00 (X is the correct offset)
when I set my timezone to Australia/Adelaide, and convert UTC time: '2022-04-02T16:30:00Z'
let dt4 = dayjs('2022-04-02T16:30:00Z');
let testTimetz4 = dayjs.tz(dt4, 'Asia/Shanghai').format('YYYY-MM-DD HH:mm:ssZ');
output: '2022-04-03 00:30:00+07:00' but Shanghai's timeOffset always stay in +8:00
here is an another case:
let dt2 = dayjs.unix(1648917000 + 1);
let testTimetz2 = dayjs.tz(dt2, 'Australia/Adelaide').format('YYYY-MM-DD HH:mm:ssZ');
output: '2022-04-03 02:00:01+08:30' correct: '2022-04-03 02:00:01+09:30'
Information
-
Day.js Version [v1.11.7]
-
OS: Windows 10 21H2
-
Time zone: [e.g. GMT+09:30 DST (Adelaide)]
the root cause of the problem src/plugin/timezone/index.js
proto.tz = function (timezone = defaultTimezone, keepLocalTime) {
const oldOffset = this.utcOffset()
const date = this.toDate()
const target = date.toLocaleString('en-US', { timeZone: timezone }) // target within timeoffset cause wrong offset in DST converting
const diff = Math.round((date - new Date(target)) / 1000 / 60) // New Date(target) is wrong
let ins = d(target).$set(MS, this.$ms)
.utcOffset((-Math.round(date.getTimezoneOffset() / 15) * 15) - diff, true)
if (keepLocalTime) {
const newOffset = ins.utcOffset()
ins = ins.add(oldOffset - newOffset, MIN)
}
ins.$x.$timezone = timezone
return ins
}
Temporary Fix Method
function isTimeZoneCorrect(dayjsDate, localTimeZone) {
let timeZones = [];
for (let i of [-2, -1, 1, 2]) {
// in order to judge the time, we use two groups of forward/backward time's offset
timeZones.push(dayjsDate.add(i, 'day').format('YYYY-MM-DD HH:mm:ss'));
}
timeZones = timeZones.map(function(i) {
// only use those timeoffset info
return dayjs.tz(i, localTimeZone).format('Z');
});
if ([...new Set(timeZones)].length > 2) {
// if N > 2, it means there are wrong times surround current time, but current input time must be true
return true;
}
return timeZones.includes(dayjsDate.format('Z')); // if our time offset in this group, it means correct time offset
}
function repairErrorTimeOffset(dayjsDate) {
return dayjsDate.utcOffset(dayjsDate.utcOffset() + 60, true);
}
you saved my day literally thanks!
This bug needs to be addressed by the dev team. It's a pretty big deal for companies who have companies all over the world sharing data.
The issue still exists on version 1.11.13