Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UTC time convert error (and temporary solving method) #2303

Open
caork opened this issue May 8, 2023 · 2 comments
Open

UTC time convert error (and temporary solving method) #2303

caork opened this issue May 8, 2023 · 2 comments

Comments

@caork
Copy link

caork commented May 8, 2023

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);
}
@gabamnml
Copy link

gabamnml commented Jul 8, 2023

you saved my day literally thanks!

@lemmylem
Copy link

lemmylem commented Jul 13, 2023

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants