最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - moment.js thinks that 2013-12-31 is week 1, not week 53 - Stack Overflow

programmeradmin0浏览0评论

The moment.js library is awesome, and I use it almost all the time, but I recently ran into something interesting. I'm trying to plot data by week of the year, and one of the data points was 2013-12-31, moment.js tells me this is week 1? Is there a better way to handle this? either with 53, null, -1, or something?

moment('2013-12-31').week()
(returns) 1

I thought maybe using isoWeek or format would get around this, but they all return the same value of 1, despite the documentation saying it goes to 53.

moment('2013-12-31').isoWeek()
(returns) 1
+moment('2013-12-31').format('w')
(returns) 1   

Anyone have any ideas on this? (short of making a test whether the week computed has a min/max date that covers the date value I passed it)

The moment.js library is awesome, and I use it almost all the time, but I recently ran into something interesting. I'm trying to plot data by week of the year, and one of the data points was 2013-12-31, moment.js tells me this is week 1? Is there a better way to handle this? either with 53, null, -1, or something?

moment('2013-12-31').week()
(returns) 1

I thought maybe using isoWeek or format would get around this, but they all return the same value of 1, despite the documentation saying it goes to 53.

moment('2013-12-31').isoWeek()
(returns) 1
+moment('2013-12-31').format('w')
(returns) 1   

Anyone have any ideas on this? (short of making a test whether the week computed has a min/max date that covers the date value I passed it)

Share Improve this question asked Sep 2, 2014 at 20:17 MarkMark 5386 silver badges18 bronze badges 1
  • your local time must be past midnight in england. pass a local time as well, or use the local features, like format() – dandavis Commented Sep 2, 2014 at 20:19
Add a comment  | 

7 Answers 7

Reset to default 5

It is because the week from the 30th december 2013 is considered to be the 1st week of 2014 as you may see on this page epoch converter

And according to momentjs documentation:

The week with January 1st in it is the first week of the year.

I had a problem at my work where we used .format('YYYY WW') for some comparison logic.

That doesn't really make sense, as you should probably use .format('gggg WW') in such cases.

moment('2013-12-31').format('YYYY w'); // Returns 2013 1
moment('2013-12-31').format('gggg w'); // Returns 2014 1

https://momentjs.com/docs/#/displaying/format/

This is expected behavior. According to the ISO 8601 standard, 2013 is not a year with 53 weeks.

The long years, with 53 weeks in them, can be described by any of the following equivalent definitions:

  • any year starting on Thursday (dominical letter D or DC) and any leap year starting on Wednesday (ED)
  • any year ending on Thursday (D, ED) and any leap year ending on Friday (DC)
  • years in which 1 January and 31 December (in common years) or either (in leap years) are Thursdays

(source)

2013 started and ended on a Tuesday so therefore it is not a "long year" and 2013-12-31 is considered part of the first week of 2014.

If you want that week to be the 53rd, you'll have to write custom code for it as the ISO standard won't agree with you!

Moment.js docs aren't that straightforward with this I had to move from WW-YYYY to WW-GGGG

moment(2019-12-30T00:20:53.380Z).format(WW-YYYY) // Gave me 01-2019 incorrectly
moment(2019-12-30T00:20:53.380Z).format(WW-GGGG) // Gave me 01-2020 correctly

Findings

  • If your doing locale weeks, use ww & gggg
  • If your doing ISO weeks, use WW & GGGG

A mix of w/W & Y is incorrect usage

I had the same problem with the calculation of the week number, starting from the date of Sunday. Finally I was able to solve the problem by calculating the week number starting not from Sunday but from Monday.

moment(date).isoWeekday(1).week()

Better right a custom method which will convert date into week and that can be customized easily.

//value  : (MMM DD YYYY format)
function getEpiWeek(value) {
    Date.prototype.getWeek = function () {
        var target = new Date(this.valueOf());
        // ISO week date weeks start on monday, so correct the day number
        var dayNr = (this.getDay() + 7) % 7;
        // Set the target to the thursday of this week so the
        // target date is in the right year
        target.setDate(target.getDate() - dayNr + 3);
        // ISO 8601 states that week 1 is the week with january 4th in it
        var jan4 = new Date(target.getFullYear(), 0, 4);
        // Number of days between target date and january 4th
        var dayDiff = (target - jan4) / 86400000;

        if (new Date(target.getFullYear(), 0, 1).getDay() < 4) {
            return 1 + Math.ceil(dayDiff / 7);
        }
        else {  // jan 4th is on the next week (so next week is week 1)
            return Math.ceil(dayDiff / 7);
        }
    };
    var weekNumber = new Date(value).getWeek()
    var year = getYear(value, weekNumber);
    return weekNumber + ' ' + year;
}   

function getYear(value, weekNumber) {
    var year = parseInt(value.split(' ')[2]);
    if (value.split(' ')[0] == 'Jan') {
        if (weekNumber > 40) {
            year = year - 1;
        }
    }
    if (value.split(' ')[0] == 'Dec') {
        if (weekNumber < 2) {
            year = year + 1;
        }
    }
    return year.toString();
}  

Personally solved my ordering issue using :

 if(d.month()==0) {
                    week = d.week();
                }else{
                    week=d.isoWeek();
                }
发布评论

评论列表(0)

  1. 暂无评论