dayjs icon indicating copy to clipboard operation
dayjs copied to clipboard

Timezone conversion incorrect when daylight saving in effect

Open PaulJNewell77 opened this issue 4 years ago • 26 comments

Describe the bug Dayjs does not seem to convert timezone correctly when DST is in effect. It produces different results from Moment. The Moment results seem intuitively what I'd expect, so believe to be correct unless there is some subtlety I'm missing.

Expected behavior With this code:

    const when = '2020-07-30T12:00:00+00:00'; // Midday GMT in summer
    console.log('Moment London: ' + moment(when).tz('Europe/London').format('HH:mm Z'));
    console.log('Moment New York: ' + moment(when).tz('America/New_York').format('HH:mm Z'));

    console.log('Dayjs London: ' + dayjs(when).tz('Europe/London').format('HH:mm Z'));
    console.log('Dayjs New York: ' + dayjs(when).tz('America/New_York').format('HH:mm Z'));

The output is:

    Moment London: 13:00 +01:00
    Moment New York: 08:00 -04:00
    Dayjs London: 12:00 +00:00 // Expect 13:00 +01:00
    Dayjs New York: 08:00 -05:00 // Expect 08:00 -04:00

Information

  • Day.js: v1.9.6
  • OS: Windows 10 Home
  • Nodejs: v12.8.3
  • Time zone: GMT+00:00

PaulJNewell77 avatar Dec 07 '20 12:12 PaulJNewell77

is this whats going wrong in the test suite of this library? i ran it and some tests were off by an hour.

alexanderankin avatar Dec 08 '20 00:12 alexanderankin

Hi, any thoughts on this issue @iamkun?

PaulJNewell77 avatar Dec 09 '20 16:12 PaulJNewell77

I can confirm that tests are failing in a locale affected by daylight savings (I'm in America/Vancouver).

I found out because tests stared breaking locally, and I made some experiments showing output different from Moment: https://runkit.com/lucasrcosta/5feca83aea7c09001b879b3a

I tried sorting it out on the code and removing the current offset from localUtcOffset on timezone/index.js fixed one test, but I couldn't figure out solutions for the others. It does seem related to not fixing DST.

Summary of all failing tests

 FAIL  test/plugin/dayOfYear.test.js
  ● DayOfYear set

    expect(received).toBe(expected) // Object.is equality
    
    Expected value to be:
      "2015-01-04T00:00:00.000Z"
    Received:
      "2014-01-05T00:00:00.000Z"

      31 |   expect(dayjs('2015-01-01T00:00:00.000Z')
      32 |     .dayOfYear(4)
    > 33 |     .toISOString()).toBe('2015-01-04T00:00:00.000Z')
      34 | 
      35 |   expect(dayjs('2015-01-01T00:00:00.000Z')
      36 |     .dayOfYear(32)
      
      at Object.<anonymous> (test/plugin/dayOfYear.test.js:33:21)

 FAIL  test/plugin/localizedFormat.test.js
  ● Should not interpolate characters inside square brackets

    expect(received).toBe(expected) // Object.is equality
    
    Expected value to be:
      "1970 l 1970"
    Received:
      "1969 l 1969"

      29 | 
      30 |   expect(actualDate.format('[l]')).toBe('l')
    > 31 |   expect(actualDate.format('YYYY [l] YYYY')).toBe('1970 l 1970')
      32 |   expect(actualDate.format('l [l] l')).toBe('1/1/1970 l 1/1/1970')
      33 |   expect(actualDate.format('[L LL LLL LLLL]')).toBe(expectedDate.format('[L LL LLL LLLL]'))
      34 | 
      
      at Object.<anonymous> (test/plugin/localizedFormat.test.js:31:46)

 FAIL  test/plugin/timezone.test.js
  ● Parse › parse timestamp, js Date, Day.js object

    expect(received).toBe(expected) // Object.is equality
    
    Expected value to be:
      "2020-08-07T12:00:00-07:00"
    Received:
      "2020-08-07T12:00:00-08:00"

      49 |     const Timestamp = dayjs.tz(d.getTime(), VAN)
      50 |     const Tmoment = moment.tz(d, VAN)
    > 51 |     expect(TjsDate.format()).toBe(result)
      52 |     expect(Tdayjs.format()).toBe(result)
      53 |     expect(Timestamp.format()).toBe(result)
      54 |     expect(Tmoment.format()).toBe(result)
      
      at Object.<anonymous> (test/plugin/timezone.test.js:51:30)

  ● Parse › parse and convert between timezones

    expect(received).toBe(expected) // Object.is equality
    
    Expected value to be:
      "2014-06-01T09:00:00-07:00"
    Received:
      "2014-06-01T09:00:00-08:00"

      57 |   it('parse and convert between timezones', () => {
      58 |     const newYork = dayjs.tz('2014-06-01 12:00', NY)
    > 59 |     expect(newYork.tz('America/Los_Angeles').format()).toBe('2014-06-01T09:00:00-07:00')
      60 |     expect(newYork.tz('Europe/London').format()).toBe('2014-06-01T17:00:00+01:00')
      61 |   })
      62 | 
      
      at Object.<anonymous> (test/plugin/timezone.test.js:59:56)

  ● Convert › convert to target time

    expect(received).toBe(expected) // Object.is equality
    
    Expected value to be:
      "2014-06-01T05:00:00-07:00"
    Received:
      "2014-06-01T05:00:00-08:00"

      74 |     const losAngeles = dayjs('2014-06-01T12:00:00Z').tz('America/Los_Angeles')
      75 |     const MlosAngeles = moment('2014-06-01T12:00:00Z').tz('America/Los_Angeles')
    > 76 |     expect(losAngeles.format()).toBe('2014-06-01T05:00:00-07:00')
      77 |     expect(losAngeles.format()).toBe(MlosAngeles.format())
      78 |     expect(losAngeles.valueOf()).toBe(1401624000000)
      79 |     expect(losAngeles.valueOf()).toBe(MlosAngeles.valueOf())
      
      at Object.<anonymous> (test/plugin/timezone.test.js:76:33)

  ● Convert › convert to target time

    expect(received).toBe(expected) // Object.is equality
    
    Expected value to be:
      "2014-06-01T05:00:00-07:00"
    Received:
      "2014-06-01T05:00:00-08:00"

      85 |     [dayjs, moment].forEach((_) => {
      86 |       const losAngeles = _('2014-06-01T12:00:00Z').tz('America/Los_Angeles')
    > 87 |       expect(losAngeles.format()).toBe('2014-06-01T05:00:00-07:00')
      88 |       expect(losAngeles.valueOf()).toBe(1401624000000)
      89 |     })
      90 |   })
      
      at forEach (test/plugin/timezone.test.js:87:35)
          at Array.forEach (<anonymous>)
      at Object.<anonymous> (test/plugin/timezone.test.js:85:21)

  ● Convert › convert from time with timezone to target time

    expect(received).toBe(expected) // Object.is equality
    
    Expected value to be:
      "2014-06-01T12:00:00Z"
    Received:
      "2014-06-01T12:00:00-01:00"

      93 |     const losAngelesInUTC = dayjs('2014-06-01T05:00:00-07:00').tz('UTC')
      94 |     const MlosAngelesInUTC = moment('2014-06-01T05:00:00-07:00').tz('UTC')
    > 95 |     expect(losAngelesInUTC.format()).toBe('2014-06-01T12:00:00Z')
      96 |     expect(losAngelesInUTC.format()).toBe(MlosAngelesInUTC.format())
      97 |   })
      98 | 
      
      at Object.<anonymous> (test/plugin/timezone.test.js:95:38)

  ● Convert › format Z

    expect(received).toBe(expected) // Object.is equality
    
    Expected value to be:
      "+09:00"
    Received:
      "+08:00"

      115 |     [dayjs, moment].forEach((_) => {
      116 |       const t = _('2020-08-06T03:48:10.258Z').tz(TOKYO)
    > 117 |       expect(t.format('Z')).toBe('+09:00')
      118 |     })
      119 |   })
      120 | })
      
      at forEach (test/plugin/timezone.test.js:117:29)
          at Array.forEach (<anonymous>)
      at Object.<anonymous> (test/plugin/timezone.test.js:115:21)

  ● DST, a time that never existed Spring Forward › 2012-03-11 02:00:00

    expect(received).toBe(expected) // Object.is equality
    
    Expected value to be:
      "2012-03-11T03:00:00-04:00"
    Received:
      "2012-03-11T04:00:00-04:00"

      143 |     const d = dayjs.tz(s, NY)
      144 |     const m = moment.tz(s, NY)
    > 145 |     expect(d.format()).toBe('2012-03-11T03:00:00-04:00')
      146 |     expect(d.format()).toBe(m.format())
      147 |     expect(d.valueOf()).toBe(m.valueOf())
      148 |     expect(d.valueOf()).toBe(1331449200000)
      
      at Object.<anonymous> (test/plugin/timezone.test.js:145:24)

  ● DST, a time that never existed Spring Forward › 2012-03-11 02:59:59

    expect(received).toBe(expected) // Object.is equality
    
    Expected value to be:
      "2012-03-11T03:59:59-04:00"
    Received:
      "2012-03-11T04:59:59-04:00"

      154 |     const d = dayjs.tz(s, NY)
      155 |     const m = moment.tz(s, NY)
    > 156 |     expect(d.format()).toBe('2012-03-11T03:59:59-04:00')
      157 |     expect(d.format()).toBe(m.format())
      158 |     expect(d.valueOf()).toBe(m.valueOf())
      159 |     expect(d.valueOf()).toBe(1331452799000)
      
      at Object.<anonymous> (test/plugin/timezone.test.js:156:24)

  ● DST, a time that never existed Spring Forward › 2012-03-11 03:00:00

    expect(received).toBe(expected) // Object.is equality
    
    Expected value to be:
      "2012-03-11T03:00:00-04:00"
    Received:
      "2012-03-11T04:00:00-04:00"

      165 |     const d = dayjs.tz(s, NY)
      166 |     const m = moment.tz(s, NY)
    > 167 |     expect(d.format()).toBe('2012-03-11T03:00:00-04:00')
      168 |     expect(d.format()).toBe(m.format())
      169 |     expect(d.valueOf()).toBe(m.valueOf())
      170 |     expect(d.valueOf()).toBe(1331449200000)
      
      at Object.<anonymous> (test/plugin/timezone.test.js:167:24)

  ● DST, a time that never existed Fall Back › 2012-11-04 02:00:00

    expect(received).toBe(expected) // Object.is equality
    
    Expected value to be:
      "2012-11-04T02:00:00-05:00"
    Received:
      "2012-11-04T01:00:00-05:00"

      204 |     [dayjs, moment].forEach((_) => {
      205 |       const d = _.tz(s, NY)
    > 206 |       expect(d.format()).toBe('2012-11-04T02:00:00-05:00')
      207 |       expect(d.utcOffset()).toBe(-300)
      208 |       expect(d.valueOf()).toBe(1352012400000)
      209 |     })
      
      at forEach (test/plugin/timezone.test.js:206:26)
          at Array.forEach (<anonymous>)
      at Object.<anonymous> (test/plugin/timezone.test.js:204:21)


Test Suites: 3 failed, 63 passed, 66 total
Tests:       12 failed, 601 passed, 613 total
Snapshots:   0 total
Time:        12.936s
Ran all test suites.

lucasrcosta avatar Dec 31 '20 20:12 lucasrcosta

This bug sounds similar to the recent comment in this one: https://github.com/iamkun/dayjs/issues/1340#issuecomment-764769936

I'm going to cross-post the bug and how it can be fixed. Let me know if that doesn't actually fix this.

Not sure your bug is similar to the OPs, unless I'm missing the connection.

But I did confirm and figure out what the problem is with your case. It's actually a pretty easy fix (I think).

The problem

I'm in CST, which has an offset of -5/-6 (depending on DST). Let's use this as an example.

Given the input you gave: 2020-03-29T00:30:00Z

The code converts to local machines timezone (at this time it was -5 for me). Then it converts to the desired timezone. These are the results:

  • 2020-03-28T20:30:00-05:00
  • 2020-03-29T03:30:00+02:00

Then these two dates are subtracted (disregard the offset), giving -07:00. Next, we take local machine offset (-5) and subtract from -7. -5 - (-7) = +2. Correct answer.

That's how it should work. Let's look at the code and I'll show you the bug.

  proto.tz = function (timezone = defaultTimezone, keepLocalTime) {
    const oldOffset = this.utcOffset()
    const target = this.toDate().toLocaleString('en-US', { timeZone: timezone })
    const diff = Math.round((this.toDate() - new Date(target)) / 1000 / 60)
    let ins = d(target).$set(MS, this.$ms).utcOffset(localUtcOffset - diff, true)
    if (keepLocalTime) {
      const newOffset = ins.utcOffset()
      ins = ins.add(oldOffset - newOffset, MIN)
    }
    ins.$x.$timezone = timezone
    return ins
  }

Source: https://github.com/iamkun/dayjs/blob/dev/src/plugin/timezone/index.js#L101

Check out that it takes localUtcOffset and subtracts the diff. That localUtcOffset is obtained by doing the following. The problem is that DST is applied now so the offset for me is -06:00, giving the offset of +01:00 that we're seeing.

  const localUtcOffset = d().utcOffset()

Source: https://github.com/iamkun/dayjs/blob/dev/src/plugin/timezone/index.js#L39

The fix

Replace localUtcOffset with this.utcOffset() and that will return the UTC offset at that date

What you should do

I haven't tested this but I think it'll work.

If that works for you, I'd encourage you to submit a PR and fix this.

When was the bug introduced

Bug has existed ever since the timezone plugin was added.

https://github.com/iamkun/dayjs/pull/974/files

addisonElliott avatar Jan 21 '21 17:01 addisonElliott

A fix was applied in #1352 that may fix this bug. Can someone try with the latest changes and see if the issue still persists?

addisonElliott avatar Jan 29 '21 14:01 addisonElliott

Still brakes here, although a little different...

Summary of all failing tests
 FAIL  test/plugin/timezone.test.js (5.167s)
  ● Convert › convert to target time

    expect(received).toBe(expected) // Object.is equality
    
    Expected value to be:
      1401624000000
    Received:
      1401620400000

      76 |     expect(losAngeles.format()).toBe('2014-06-01T05:00:00-07:00')
      77 |     expect(losAngeles.format()).toBe(MlosAngeles.format())
    > 78 |     expect(losAngeles.valueOf()).toBe(1401624000000)
      79 |     expect(losAngeles.valueOf()).toBe(MlosAngeles.valueOf())
      80 |     expect(losAngeles.utcOffset()).toBe(-420)
      81 |     expect(losAngeles.utcOffset()).toBe(MlosAngeles.utcOffset())
      
      at Object.<anonymous> (test/plugin/timezone.test.js:78:34)

  ● Convert › convert to target time

    expect(received).toBe(expected) // Object.is equality
    
    Expected value to be:
      1401624000000
    Received:
      1401620400000

      86 |       const losAngeles = _('2014-06-01T12:00:00Z').tz('America/Los_Angeles')
      87 |       expect(losAngeles.format()).toBe('2014-06-01T05:00:00-07:00')
    > 88 |       expect(losAngeles.valueOf()).toBe(1401624000000)
      89 |     })
      90 |   })
      91 | 
      
      at forEach (test/plugin/timezone.test.js:88:36)
          at Array.forEach (<anonymous>)
      at Object.<anonymous> (test/plugin/timezone.test.js:85:21)

  ● DST, a time that never existed Spring Forward › 2012-03-11 02:00:00

    expect(received).toBe(expected) // Object.is equality
    
    Expected value to be:
      "2012-03-11T03:00:00-04:00"
    Received:
      "2012-03-11T04:00:00-04:00"

      145 |     const d = dayjs.tz(s, NY)
      146 |     const m = moment.tz(s, NY)
    > 147 |     expect(d.format()).toBe('2012-03-11T03:00:00-04:00')
      148 |     expect(d.format()).toBe(m.format())
      149 |     expect(d.valueOf()).toBe(m.valueOf())
      150 |     expect(d.valueOf()).toBe(1331449200000)
      
      at Object.<anonymous> (test/plugin/timezone.test.js:147:24)

  ● DST, a time that never existed Spring Forward › 2012-03-11 02:59:59

    expect(received).toBe(expected) // Object.is equality
    
    Expected value to be:
      "2012-03-11T03:59:59-04:00"
    Received:
      "2012-03-11T04:59:59-04:00"

      156 |     const d = dayjs.tz(s, NY)
      157 |     const m = moment.tz(s, NY)
    > 158 |     expect(d.format()).toBe('2012-03-11T03:59:59-04:00')
      159 |     expect(d.format()).toBe(m.format())
      160 |     expect(d.valueOf()).toBe(m.valueOf())
      161 |     expect(d.valueOf()).toBe(1331452799000)
      
      at Object.<anonymous> (test/plugin/timezone.test.js:158:24)

  ● DST, a time that never existed Spring Forward › 2012-03-11 03:00:00

    expect(received).toBe(expected) // Object.is equality
    
    Expected value to be:
      "2012-03-11T03:00:00-04:00"
    Received:
      "2012-03-11T04:00:00-04:00"

      167 |     const d = dayjs.tz(s, NY)
      168 |     const m = moment.tz(s, NY)
    > 169 |     expect(d.format()).toBe('2012-03-11T03:00:00-04:00')
      170 |     expect(d.format()).toBe(m.format())
      171 |     expect(d.valueOf()).toBe(m.valueOf())
      172 |     expect(d.valueOf()).toBe(1331449200000)
      
      at Object.<anonymous> (test/plugin/timezone.test.js:169:24)

  ● DST, a time that never existed Fall Back › 2012-11-04 02:00:00

    expect(received).toBe(expected) // Object.is equality
    
    Expected value to be:
      "2012-11-04T02:00:00-05:00"
    Received:
      "2012-11-04T01:00:00-05:00"

      206 |     [dayjs, moment].forEach((_) => {
      207 |       const d = _.tz(s, NY)
    > 208 |       expect(d.format()).toBe('2012-11-04T02:00:00-05:00')
      209 |       expect(d.utcOffset()).toBe(-300)
      210 |       expect(d.valueOf()).toBe(1352012400000)
      211 |     })
      
      at forEach (test/plugin/timezone.test.js:208:26)
          at Array.forEach (<anonymous>)
      at Object.<anonymous> (test/plugin/timezone.test.js:206:21)

 FAIL  test/plugin/localizedFormat.test.js
  ● Should not interpolate characters inside square brackets

    expect(received).toBe(expected) // Object.is equality
    
    Expected value to be:
      "1970 l 1970"
    Received:
      "1969 l 1969"

      29 | 
      30 |   expect(actualDate.format('[l]')).toBe('l')
    > 31 |   expect(actualDate.format('YYYY [l] YYYY')).toBe('1970 l 1970')
      32 |   expect(actualDate.format('l [l] l')).toBe('1/1/1970 l 1/1/1970')
      33 |   expect(actualDate.format('[L LL LLL LLLL]')).toBe(expectedDate.format('[L LL LLL LLLL]'))
      34 | 
      
      at Object.<anonymous> (test/plugin/localizedFormat.test.js:31:46)

 FAIL  test/plugin/dayOfYear.test.js
  ● DayOfYear set

    expect(received).toBe(expected) // Object.is equality
    
    Expected value to be:
      "2015-01-04T00:00:00.000Z"
    Received:
      "2014-01-05T00:00:00.000Z"

      31 |   expect(dayjs('2015-01-01T00:00:00.000Z')
      32 |     .dayOfYear(4)
    > 33 |     .toISOString()).toBe('2015-01-04T00:00:00.000Z')
      34 | 
      35 |   expect(dayjs('2015-01-01T00:00:00.000Z')
      36 |     .dayOfYear(32)
      
      at Object.<anonymous> (test/plugin/dayOfYear.test.js:33:21)


Test Suites: 3 failed, 68 passed, 71 total
Tests:       8 failed, 648 passed, 656 total
Snapshots:   0 total
Time:        12.402s
Ran all test suites.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

dayjs on  dev is 📦 v0.0.0-development took 20s 982ms 
➜ git pull
Already up to date.```

lucasrcosta avatar Jan 29 '21 16:01 lucasrcosta

I'm getting the same problem now that we're in BST, I'm in Europe/London timezone and this is what I'm getting:

  • Date Time: 2021-04-15 14:00:00
  • console.log(this.$dayjs.tz('2021-04-15 14:00:00', 'UTC').toISOString()) // gives 2021-04-15 14:00:00
  • console.log(this.$dayjs.tz('2021-04-15 14:00:00', 'Europe/London').toISOString()) // gives 2021-04-15 13:00:00

Clearly wrong, any suggestions?

sts-ryan-holton avatar Apr 15 '21 15:04 sts-ryan-holton

Has this been fixed?. I am having the same issue with a few different time zones that apply daylight savings time, or has anyone been successful with any work around?,

hhamud avatar May 18 '21 18:05 hhamud

It sounds like it hasn't. I thought #1352 would fix it but others have reported not. Note that these changes are not officially released. In other words, you have to use the dev branch in order to get the latest changes.

If you're interested, try with the dev branch and see if it's still broken

addisonElliott avatar May 18 '21 18:05 addisonElliott

It sounds like it hasn't. I thought #1352 would fix it but others have reported not. Note that these changes are not officially released. In other words, you have to use the dev branch in order to get the latest changes.

If you're interested, try with the dev branch and see if it's still broken

Thanks for the tip. I've tried to install the dev branch however it still does not fix my issue.

hhamud avatar May 18 '21 19:05 hhamud

Seems the issue still in place.

I tried to run this script in different time zones and got quite diverged results.

console.log(dayjs("2027-10-31T00:00:00Z").tz("Europe/Berlin").format());

console.log(dayjs("2027-10-31T01:00:00Z").tz("Europe/Berlin").format()); // +1hr

ServerTime: Wed Sep 15 2021 08:14:59 GMT+0200 (Central European Summer Time)

2027-10-31T02:00:00+02:00
2027-10-31T02:00:00Z

ServerTime: Wed Sep 15 2021 07:15:53 GMT+0100 (British Summer Time)

2027-10-31T02:00:00+03:00
2027-10-31T02:00:00+01:00

ServerTime: Wed Sep 15 2021 16:16:46 GMT+1000 (Vladivostok Standard Time)

2027-10-31T02:00:00+02:00
2027-10-31T02:00:00+01:00

This issue affects also development process when remote developers run it on their own local machines across the world.

I expect to have the same result which is not related to the server's timezone.

Please correct me if I'm wrong.

dobeerman avatar Sep 15 '21 06:09 dobeerman

Seems related to https://github.com/iamkun/dayjs/issues/1412

and also related to: https://github.com/iamkun/dayjs/issues/1408

CoreyKovalik avatar Oct 29 '21 19:10 CoreyKovalik

The problem is still relevant.

Serg-Mois avatar Mar 15 '22 18:03 Serg-Mois

The problem is still relevant.

Last November we moved from dayjs to luxon and never looked back. This March we now have no issues traversing the DST boundary :)

CoreyKovalik avatar Mar 15 '22 19:03 CoreyKovalik

The problem is still relevant.

Last November we moved from dayjs to luxon and never looked back. This March we now have no issues traversing the DST boundary :)

@CoreyKovalik we have a big project, it will be much longer to switch to luxon, due to the API differences.

Serg-Mois avatar Mar 16 '22 09:03 Serg-Mois

a year and a half after this bug was reported and it's still no fixed? damn... should i revert to momentjs after all?

AComasSamcla avatar May 26 '22 10:05 AComasSamcla

@AComasSamcla I didn't check, but looks like fixed in https://github.com/iamkun/dayjs/releases/tag/v1.11.2

fix UTC plugin .valueOf not taking DST into account (https://github.com/iamkun/dayjs/issues/1448) (27d1c50)

Serg-Mois avatar May 26 '22 11:05 Serg-Mois

@Serg-Mois oh nice, i checked it and seems fixed now, so probably this issue could be closed by @iamkun too. Thanks!

AComasSamcla avatar May 27 '22 05:05 AComasSamcla

The issue remains,

    "dayjs": {
      "version": "1.11.5",

EDIT: updated to 1.11.6, the issue remains.

dayjs.utc("2022-04-22 15:08:45").unix() // wrong, expected: 1650640125, actual: 1650636525 
dayjs.utc("2022-08-22 15:08:45").unix() // wrong, expected: 1661180925, actual: 1661177325
dayjs.utc("2022-01-22 15:08:45").unix() // ok, expected: 1642864125, actual: 1642864125

Verified with unixtimestamp.com and python.

EDIT2: If the time is specified this way then the conversion is correct,

dayjs.utc("2022-04-22T15:08:45.000Z").unix() // ok, expected: 1650640125, actual: 1650640125

thomasnal avatar Nov 19 '22 19:11 thomasnal

was there ever a solution for this?

WarrenBuffering avatar Oct 20 '23 04:10 WarrenBuffering

Just noting that this is still an issue in 1.11.10

jonah-ullman avatar Nov 16 '23 23:11 jonah-ullman

Any updates on this issue? Still facing the same in latest version

sanket-mundada avatar May 10 '24 08:05 sanket-mundada

I am with the same problem.

vladimircosta11 avatar Jun 24 '24 18:06 vladimircosta11

Same here, facing issues with DST handling.

Aki0x137 avatar Jul 22 '24 05:07 Aki0x137

It's been almost 4 years and still no fix.. I just came across the same issue.
It's happening when subtracting 6 months, off by 1 hour

nabak9 avatar Jul 23 '24 12:07 nabak9

Ha, I came across the same issue and couldn't figure it out until reading this --- is this still not fixed?

njoshi22 avatar Aug 15 '24 14:08 njoshi22

I'm not sure if I got this wrong, but for whatever reason setting the 'keepLocalTime' to 'false' will correctly display the time in regions affected by DST.

I have a function like this:

    function getHRT(datetime) {
        return dayjs(datetime)
            .tz(timezone, false) // Put the 'false' here when setting the timezone.
            .format(date_format + ', ' + time_format);
    }

I'm working with a VILT stack, not sure if that has anything to do with it. Can someone else please confirm?

amir-huseinspahic avatar Sep 13 '24 09:09 amir-huseinspahic

@amir-huseinspahic I don't think it is meant for that. See when keepLocalTime was introduced: https://github.com/iamkun/dayjs/issues/1149

It seems to me that if you want to say it is 6:00 in timezone 1 and want to change it to 6:00 in timezone 2, then pass in keepLocalTime = true. Otherwise, it will change the time to match the same moment 6:00 in timezone 1.

If keepLocalTime works, that's interesting, but it may not always.

triemstr avatar Sep 17 '24 22:09 triemstr

Workaround for me due to confusion on timezones is to use Date directly for this purpose (which I only need in one spot in my code) whereas I use dayjs in many areas.

const date1 = new Date('December 1, 1975 23:15:30 GMT');
const date2 = new Date('August 1, 1975 23:15:30 GMT');
const date3 = new Date('January 1, 1975 23:15:30 GMT');

console.log(date1.getTimezoneOffset());
// Expected output: your local timezone offset in minutes from GMT
// In Pacific time (your results will vary): 480.

console.log(date2.getTimezoneOffset());
// Expected output: your local timezone offset in minutes from GMT
// In Pacific time (your results will vary): 420.

console.log(date1.getTimezoneOffset() === date2.getTimezoneOffset());
// Expected output: false -- Since different offsets due to daylight savings in summer.

console.log(date1.getTimezoneOffset() === date3.getTimezoneOffset());
// Expected output: true -- Same offset in winter despite two different winter dates.

tl;dr - I really just use this only in my code:

const tzOffsetHours = new Date().getTimezoneOffset()/60;
console.log(tzOffsetHours);
// Expected output today, September 17, 2024 (still daylight savings) in the Pacific Time zone in hours: 7

You could instead pull your dayjs formatted date and put into the Date object or compare to the system time somehow or find some other way to use the IANA database if issues with dayjs until dayjs is updated. I played with Date code here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset

Another workaround: https://github.com/iamkun/dayjs/issues/1388#issuecomment-1436092421

triemstr avatar Sep 17 '24 23:09 triemstr

If such a core bug affecting so many users hasn't been fixed in 4 years, consider dayjs abandoned. Fairwell.

AntonioLuisME avatar Sep 26 '24 12:09 AntonioLuisME