diff --git a/src/plugin/timezone/index.js b/src/plugin/timezone/index.js index bcacf9ab6..3479d9323 100644 --- a/src/plugin/timezone/index.js +++ b/src/plugin/timezone/index.js @@ -126,9 +126,13 @@ export default (o, c, d) => { if (!this.$x || !this.$x.$timezone) { return oldStartOf.call(this, units, startOf) } - - const withoutTz = d(this.format('YYYY-MM-DD HH:mm:ss:SSS'), { locale: this.$L }) - const startOfWithoutTz = oldStartOf.call(withoutTz, units, startOf) + let ins + if (this.$x.$timezone.toUpperCase() === 'UTC') { + ins = d(this.format('YYYY-MM-DD HH:mm:ss:SSS'), {locale: this.$L, utc: true }) + } else { + ins = d(this.format('YYYY-MM-DD HH:mm:ss:SSS'), { locale: this.$L }) + } + const startOfWithoutTz = oldStartOf.call(ins, units, startOf) return startOfWithoutTz.tz(this.$x.$timezone, true) } diff --git a/test/plugin/transitionDSTtoUTC.test.js b/test/plugin/transitionDSTtoUTC.test.js new file mode 100644 index 000000000..f7dc69761 --- /dev/null +++ b/test/plugin/transitionDSTtoUTC.test.js @@ -0,0 +1,29 @@ +import dayjs from '../../src' +import utc from '../../src/plugin/utc' +import timezone from '../../src/plugin/timezone' + +dayjs.extend(utc) +dayjs.extend(timezone) + +describe('timezone', () => { + it('should preserve UTC semantics for startOf(day) across host DST transitions', () => { + // 2024-11-03 is the DST fall-back date in America/Los_Angeles. + // When the host timezone is set to America/Los_Angeles, + // dayjs.tz(ms, 'UTC') should still behave exactly like dayjs.utc(ms). + + const ms = Date.parse('2024-11-03T23:00:00.000Z') + + const tzResult = dayjs + .tz(ms, 'UTC') + .startOf('day') + .valueOf() + + const utcResult = dayjs + .utc(ms) + .startOf('day') + .valueOf() + + expect(tzResult).toBe(utcResult) + expect(tzResult).toBe(Date.parse('2024-11-03T00:00:00.000Z')) + }) +}) \ No newline at end of file