dayjs icon indicating copy to clipboard operation
dayjs copied to clipboard

isoWeek return wrong date.

Open kavinwang opened this issue 7 months ago • 4 comments

nodejs: v22.11.0 dayjs: 1.11.13

script: dayjs('2021-01-01').isoWeek(30).format('YYYY-MM-DD') returns '2020-07-24'

dayjs('2021-01-02').isoWeek(30).format('YYYY-MM-DD') returns '2020-07-25'

dayjs('2021-01-03').isoWeek(30).format('YYYY-MM-DD') returns '2020-07-26'

dayjs('2021-01-04').isoWeek(30).format('YYYY-MM-DD') '2021-07-26', start here, it seems ok.

Information

  • Day.js v22.11.0
  • [OS: [e.g. iOS]](nodejs: v22.11.0)

maybe i misunderstand the isoweek.

kavinwang avatar May 07 '25 04:05 kavinwang

Hey @kavinwang !

I'm not 100% sure I understand your issue, but to me, everything seems correct.

If you take a look at https://www.epochconverter.com/weeks/2021, the first ISO week of 2021 began on January 4th 2021. Therefore, any dates before then would then should reference week 30 of 2020 (which started on July 20th 2020).

As for the dates incrementing, this is due to dayjs choosing the offset to use based on the day of the week, and not the date itself when using isoWeek.

January 1st 2021 was a Friday, and the Friday in week 30 of 2020 was July 24th 2020. January 2nd was Saturday in 2021, and Saturday in week 30 of 2020 was July 25th 2020 (etc.).

If you need to ensure you always return the start of an ISO Week, it is advised to therefore always use a Monday.

Hope that helps :)

abiciao avatar May 09 '25 10:05 abiciao

It seems to me that isoWeek mixes up utc dates and local dates 🤔

> dayjs(new Date('2025-10-05T20:00:00Z')).isoWeek()
40
> dayjs(new Date('2025-10-05T21:00:00Z')).isoWeek()
41
> new Date()
2025-06-05T06:59:32.740Z
> new Date().toString()
'Thu Jun 05 2025 10:00:00 GMT+0300 (Eastern European Summer Time)'
>

As you can see from example, I'm in GMT+3, so end of the week at 21:00 correlates with midnight for me locally. But with isoWeek I'd assume I get isoWeek for the time zone my date is in, not my local time zone.

kblcuk avatar Jun 05 '25 07:06 kblcuk

Hey @kblcuk !

JavaScript Date objects internally represent time as a UTC timestamp — a single point on the timeline. They don’t store any timezone information. When you create a date like:

new Date('2025-10-05T20:00:00Z') that’s an absolute moment in UTC, no questions asked. Date.toString converts for you, but dayjs doesn't unless you tell it to explicitly. To force a conversion with isoWeek in particular, you'd need to use the utc or timezone plugin.

Sucks, but that's just dates in JS :/

abiciao avatar Jun 05 '25 07:06 abiciao

Ah, right, I wasn't aware that there is explicit dayjs.utc (somewhat akin to moment, should've known 😅);

So these work as expected:

> dayjs.utc(new Date('2025-10-05T21:00:00Z')).isoWeek()
40
> dayjs.utc(new Date('2025-10-05T20:00:00Z')).isoWeek()
40
> dayjs.utc(new Date('2025-10-05T23:59:59Z')).isoWeek()
40

Thanks, @abiciao; I very much suspect that OPs issue also comes from this.

kblcuk avatar Jun 05 '25 07:06 kblcuk