Moment: Wrong week number is returned from the "week()" function

Created on 19 Jul 2018  ·  5Comments  ·  Source: moment/moment

Description of the Issue and Steps to Reproduce:
When creating a date, for example [2018, 11, 29], and performing the week function the result is 52, but for [2018, 11, 30] and for 31 as well it returns 1. The expected result is 52.

Example

const a = moment([2018, 11, 29]);
console.log('a', a.year(), a.week());
//a 2018 52

const b = moment([2018, 11, 30]);
console.log('b', b.year(), b.week());
//b 2018 1

jsbin live example

Environment:
Safari 11.1.2 on OSX

Other information that may be helpful:

"Thu Jul 19 2018 16:52:11 GMT+0200 (CEST)"
"7/19/2018, 4:52:11 PM"
-120
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.1.2 Safari/605.1.15"
"2.14.1"

Most helpful comment

I think you probably have an expectation of how week-numbering works that differs from established practice.

e.g. you think 1st January is always in week 1, and 31st December is always in week 52/53 - and, to be fair, some wall calendars do show week numbering like that.

When it comes to standardising week numbers, the preference is to ensure that a week always contains 7 days. For the ISO standard: weeks runs from Monday-Sunday, and week 1 contains the first Thursday of the year. Which means Monday-Wednesday of week 1 _may_ fall in the previous year. (this'll happen in 2019/2020: December 29th-31st of 2019 are considered as part of Week 1 of 2020)

You're not using the ISO methods (isoWeek() / isoWeekYear()), so you're relying on your locale's definition of a week, which is running from Sunday - Saturday.

December 30th 2018 is a Sunday, and the first day of a week in your locale. Only 2 days of that week fall in 2018, the rest of it is in 2019. The rules for your locale are used to decide whether that week (all 7 days) are classed as 2018 week 53, or 2019 week 1. In your case, they've said 2019 week 1.

All 5 comments

We encounter the same problem.
console.log(moment("2018-w15", "YYYY-[w]WW").add(38, "weeks").format("YYYY-[w]WW"))
shows 2018-w01

@numen31337 You probably want to be using weekYear() instead of year()

@Blapi WW is the ISO Week, so you most likely need to use GGGG instead of YYYY when formatting (GGGG is the ISO "Week Year")

I'll clarify this a bit, here is code with dates and related output:

const a = moment([2018, 11, 29]);
console.log(
            `a year: ${a.year()}`,  //a year: 2018
            `a month: ${a.month()}`, //a month: 11
            `a date: ${a.date()}`, //a date: 29
            `a week: ${a.week()}`, //a week: 52
            `a weekYear: ${a.weekYear()}`, //a weekYear: 2018
);

const b = moment([2018, 11, 30]);
console.log(
            `b year: ${b.year()}`, //b year: 2018
            `b month: ${b.month()}`, //b month: 11
            `b date: ${b.date()}`, //b date: 30
            `b week: ${b.week()}`, //b week: 1 <=== Why 1?
            `b weekYear: ${b.weekYear()}`, //b weekYear: 2019 <=== Why 2019?
);

The issue for me is that week for 2018, 11, 30 returns 1 instead of 52. Maybe I misunderstood some concepts of this library? In the long run, my task was to calculate the number of the calendar weeks between two dates and I've done this with the following workaround:

const fromDateStartWeek = fromDate.startOf('week');
const toDateStartWeek = toDate.startOf('week');
return toDateStartWeek.diff(fromDateStartWeek, 'weeks');

But I still wundering about this week function. Is this a bug or I miss something? I coming from the native developement and quite new to the javascript. Thank you.

I think you probably have an expectation of how week-numbering works that differs from established practice.

e.g. you think 1st January is always in week 1, and 31st December is always in week 52/53 - and, to be fair, some wall calendars do show week numbering like that.

When it comes to standardising week numbers, the preference is to ensure that a week always contains 7 days. For the ISO standard: weeks runs from Monday-Sunday, and week 1 contains the first Thursday of the year. Which means Monday-Wednesday of week 1 _may_ fall in the previous year. (this'll happen in 2019/2020: December 29th-31st of 2019 are considered as part of Week 1 of 2020)

You're not using the ISO methods (isoWeek() / isoWeekYear()), so you're relying on your locale's definition of a week, which is running from Sunday - Saturday.

December 30th 2018 is a Sunday, and the first day of a week in your locale. Only 2 days of that week fall in 2018, the rest of it is in 2019. The rules for your locale are used to decide whether that week (all 7 days) are classed as 2018 week 53, or 2019 week 1. In your case, they've said 2019 week 1.

Thank you for the clarification. That's really surprising for me. I really miss the API like from Apple Calendar dateComponents(_:from:to:) where you can ask for a diff in specific components, in my case Calendar.current.dateComponents([.weekOfYear], from: sinceDay, to: targetDay) and receive the diff in the real weeks of the year, not just days / 7.

Was this page helpful?
0 / 5 - 0 ratings