【问题标题】:moment JS get number of weeks in a monthmoment JS 获得一个月的周数
【发布时间】:2015-02-07 17:01:26
【问题描述】:

我正在尝试使用 Moment js 计算一个月中的周数。但我在 2015 年 5 月和 2015 年 8 月的几个月里得到了错误的结果。

我正在使用此代码。

var start = moment().startOf('month').format('DD');
var end = moment().endOf('month').format('DD');
var weeks = (end-start+1)/7;
weeks = Math.ceil(weeks);

moment JS 中是否有任何预构建的方法来获取周数。

【问题讨论】:

  • startend 是整数还是字符串?
  • thisthis 的可能回购??
  • 你得到了什么结果,你期待什么?

标签: javascript momentjs


【解决方案1】:

编辑:

新的并且希望非常正确的实现:

function calcWeeksInMonth(date: Moment) {
  const dateFirst = moment(date).date(1);
  const dateLast = moment(date).date(date.daysInMonth());
  const startWeek = dateFirst.isoWeek();
  const endWeek = dateLast.isoWeek();

  if (endWeek < startWeek) {
    // Yearly overlaps, month is either DEC or JAN
    if (dateFirst.month() === 0) {
      // January
      return endWeek + 1;
    } else {
      // December
      if (dateLast.isoWeekday() === 7) {
        // Sunday is last day of year
        return endWeek - startWeek + 1;
      } else {
        // Sunday is NOT last day of year
        return dateFirst.isoWeeksInYear() - startWeek + 1;
      }
    }
  } else {
    return endWeek - startWeek + 1;
  }
}

为以下日期输出以下值:

calcWeeksInMonth(moment("2016-12-01")); // 5

calcWeeksInMonth(moment("2017-01-01")); // 6
calcWeeksInMonth(moment("2017-02-01")); // 5
calcWeeksInMonth(moment("2017-03-01")); // 5
calcWeeksInMonth(moment("2017-04-01")); // 5
calcWeeksInMonth(moment("2017-05-01")); // 5
calcWeeksInMonth(moment("2017-06-01")); // 5
calcWeeksInMonth(moment("2017-07-01")); // 6
calcWeeksInMonth(moment("2017-08-01")); // 5
calcWeeksInMonth(moment("2017-09-01")); // 5
calcWeeksInMonth(moment("2017-10-01")); // 6
calcWeeksInMonth(moment("2017-11-01")); // 5
calcWeeksInMonth(moment("2017-12-01")); // 5

calcWeeksInMonth(moment("2018-01-01")); // 5

旧且非常不正确的实现:

calcWeeksInMonth(date) {
    const dateFirst = moment(date).date(1)
    const dateLast = moment(date).date(date.daysInMonth())
    const startWeek = dateFirst.week()
    const endWeek = dateLast.week()
    if (endWeek < startWeek) {
        return dateFirst.weeksInYear() - startWeek + 1 + endWeek
    } else {
        return endWeek - startWeek + 1
    }
}

这似乎输出了正确的结果,如果我遗漏了什么欢迎反馈!

【讨论】:

  • 同样的错误:2017 年 12 月输出 6 周而不是 5 周
  • @torvin 我用更正的实现更新了我的答案。如果您有时间在某个时候验证它,那就太棒了!无论如何,感谢您对旧实施的反馈! ?
  • @jonruna 这是对“旧的和不正确的实现”的看法(但希望是正确的!):stackoverflow.com/a/60693500/352375
【解决方案2】:

这里是javaScript版本

var year = 2021
        var  month = 6 
        var  startDate = moment([year, month])

        //Get the first and last day of the month
       var firstDay = moment(startDate).startOf('month')
       var  endDay = moment(startDate).endOf('month')
     
        //Create a range for the month we can iterate through
       var  monthRange = moment.range(firstDay, endDay)
       
        //Get all the weeks during the current month
       var  weeks = []
        var indexOf = [].indexOf;

        monthRange.by('days', function (moment) {
            var ref;
            if (ref = moment.week(), indexOf.call(weeks, ref) < 0) {
                return weeks.push(moment.week());
            }
        });
      

        var calendar, firstWeekDay, i, lastWeekDay, len, week, weekRange;

        calendar = [];

        for (i = 0, len = weeks.length; i < len; i++) {
            week = weeks[i];
            // Create a range for that week between 1st and 7th day
            firstWeekDay = moment().week(week).day(0);
            lastWeekDay = moment().week(week).day(6);
            weekRange = moment.range(firstWeekDay, lastWeekDay);
         
            // Add to the calendar
            calendar.push(weekRange);
        }

【讨论】:

  • 以上脚本是必须的
  • 感谢您提供此代码 sn-p,它可能会提供一些有限的即时帮助。 proper explanation 将通过展示为什么这是解决问题的好方法,并使其对有其他类似问题的未来读者更有用,从而大大提高其长期价值。请edit您的回答添加一些解释,包括您所做的假设。
【解决方案3】:

它使用“moment.js”显示一个月中的周列表。
它是用 angular 6+ 的打字稿编写的。

使用“npm i moment”安装 moment

在 ts 文件中。

weeks_in_month() {
    let year = 2019;  // change year
    let month = 4; // change month here
    let startDate = moment([year, month - 1])
    let endDate = moment(startDate).endOf('month');

    var dates = [];
    var weeks = [];

    var per_week = [];
    var difference = endDate.diff(startDate, 'days');

    per_week.push(startDate.toDate())
    let index = 0;
    let last_week = false;
    while (startDate.add(1, 'days').diff(endDate) < 0) {
      if (startDate.day() != 0) {
        per_week.push(startDate.toDate())
      }
      else {
        if ((startDate.clone().add(7, 'days').month() == (month - 1))) {
          weeks.push(per_week)
          per_week = []
          per_week.push(startDate.toDate())
        }
        else if (Math.abs(index - difference) > 0) {
          if (!last_week) {
            weeks.push(per_week);
            per_week = [];
          }
          last_week = true;
          per_week.push(startDate.toDate());
        }
      }
      index += 1;
      if ((last_week == true && Math.abs(index - difference) == 0) ||
        (Math.abs(index - difference) == 0 && per_week.length == 1)) {
        weeks.push(per_week)
      }
      dates.push(startDate.clone().toDate());
    }
    console.log(weeks);
}

结果:

日期时刻数组。

[Array(6), Array(7), Array(7), Array(7), Array(3)]

0: (6) [Mon Apr 01 2019 00:00:00 GMT+0530 (India Standard Time),  
Tue Apr 02 2019 00:00:00 GMT+0530 (India Standard Time),  
Wed Apr 03 2019 00:00:00 GMT+0530 (India Standard Time),  
Thu Apr 04 2019 00:00:00 GMT+0530 (India Standard Time),  
Fri Apr 05 2019 00:00:00 GMT+0530 (India Standard Time),  
Sat Apr 06 2019 00:00:00 GMT+0530 (India Standard Time)]

1: (7) [Sun Apr 07 2019 00:00:00 GMT+0530 (India Standard Time),  
Mon Apr 08 2019 00:00:00 GMT+0530 (India Standard Time),  
Tue Apr 09 2019 00:00:00 GMT+0530 (India Standard Time),  
Wed Apr 10 2019 00:00:00 GMT+0530 (India Standard Time),  
Thu Apr 11 2019 00:00:00 GMT+0530 (India Standard Time),  
Fri Apr 12 2019 00:00:00 GMT+0530 (India Standard Time),  
Sat Apr 13 2019 00:00:00 GMT+0530 (India Standard Time)]

2: (7) [Sun Apr 14 2019 00:00:00 GMT+0530 (India Standard Time),  
Mon Apr 15 2019 00:00:00 GMT+0530 (India Standard Time),  
Tue Apr 16 2019 00:00:00 GMT+0530 (India Standard Time),  
Wed Apr 17 2019 00:00:00 GMT+0530 (India Standard Time),  
Thu Apr 18 2019 00:00:00 GMT+0530 (India Standard Time),  
Fri Apr 19 2019 00:00:00 GMT+0530 (India Standard Time),  
Sat Apr 20 2019 00:00:00 GMT+0530 (India Standard Time)]

3: (7) [Sun Apr 21 2019 00:00:00 GMT+0530 (India Standard Time),  
Mon Apr 22 2019 00:00:00 GMT+0530 (India Standard Time),  
Tue Apr 23 2019 00:00:00 GMT+0530 (India Standard Time),  
Wed Apr 24 2019 00:00:00 GMT+0530 (India Standard Time),  
Thu Apr 25 2019 00:00:00 GMT+0530 (India Standard Time),  
Fri Apr 26 2019 00:00:00 GMT+0530 (India Standard Time),  
Sat Apr 27 2019 00:00:00 GMT+0530 (India Standard Time)]

4: (3) [Sun Apr 28 2019 00:00:00 GMT+0530 (India Standard Time),  
Mon Apr 29 2019 00:00:00 GMT+0530 (India Standard Time),  
Tue Apr 30 2019 00:00:00 GMT+0530 (India Standard Time)]

【讨论】:

  • 您的星期从星期日开始,但我们可以用您的脚本将其编辑到星期一吗?
【解决方案4】:

我创建了这个 gist 来查找给定月份和年份中的所有星期。通过计算calendar的长度,就可以知道周数了。

https://gist.github.com/guillaumepiot/095b5e02b4ca22680a50

# year and month are variables
year = 2015
month = 7 # August (0 indexed)
startDate = moment([year, month])

# Get the first and last day of the month
firstDay = moment(startDate).startOf('month')
endDay = moment(startDate).endOf('month')

# Create a range for the month we can iterate through
monthRange = moment.range(firstDay, endDay)

# Get all the weeks during the current month
weeks = []
monthRange.by('days', (moment)->
    if moment.week() not in weeks
        weeks.push(moment.week())
)

# Create a range for each week
calendar = []
for week in weeks
    # Create a range for that week between 1st and 7th day
    firstWeekDay = moment().week(week).day(1)
    lastWeekDay = moment().week(week).day(7)
    weekRange = moment.range(firstWeekDay, lastWeekDay)

    # Add to the calendar
    calendar.push(weekRange)

console.log calendar

【讨论】:

  • 请注意,您需要moment.jsmoment-range.js 才能运行此脚本。
【解决方案5】:

可以使用原始 javascript 轻松完成:

function getNumWeeksForMonth(year,month){
              date = new Date(year,month-1,1);
              day = date.getDay();
              numDaysInMonth = new Date(year, month, 0).getDate();
              return Math.ceil((numDaysInMonth + day) / 7);
}

你得到第一天的天数索引,加上天数来弥补第一周损失的天数,除以7用ceil加1,下周最简单溢出

【讨论】:

  • 这会导致 2017 年 12 月的结果不正确。结果将在 6 周内得到,而不是 5 周
【解决方案6】:

function getWeekNums(momentObj) {
    var clonedMoment = moment(momentObj), first, last;

    // get week number for first day of month
    first = clonedMoment.startOf('month').week();
    // get week number for last day of month
    last = clonedMoment.endOf('month').week();

    // In case last week is in next year
    if( first > last) {
        last = first + last;
    }
    return last - first + 1;
}

【讨论】:

  • 旧线程 - 我写这个是为了记录。如果您在 2017 年 12 月运行此方法,则该方法返回 2。发生这种情况的原因是因为第一周 (48) 大于上周 (1),即下个月的第一周。您尝试使用“first > last”块来解释这一点,但是,这最终使最后一周成为 49。数学应该是: if( first > last ){ last = 52+last }
  • @eugene 但如果你这样做,你还必须编辑返回:不加 1。我正确吗?
【解决方案7】:

这是最好的出路,效果很好

moment.relativeTime.dd = function (number) {
    // round to the closest number of weeks
    var weeks = Math.round(number / 7);
    if (number < 7) {
        // if less than a week, use days
        return number + " days";
    } else {
        // pluralize weeks
        return weeks + " week" + (weeks === 1 ? "" : "s"); 
    }
}

来源:How to get duration in weeks with Moment.js?

【讨论】:

    【解决方案8】:

    我还没有看到适用于所有情况的解决方案。我尝试了所有这些,但它们都以某种方式存在缺陷。同上几个 moment.js github 线程。这是我的绝妙之处:

    getNumberOfWeeksInMonth = (momentDate) => {
      const monthStartWeekNumber = momentDate.startOf('month').week();
    
      const distinctWeeks = {
        [monthStartWeekNumber]: true
      };
    
      let startOfMonth = momentDate.clone().startOf('month');
      let endOfMonth = momentDate.clone().endOf('month');
    
      //  this is an 'inclusive' range -> iterates through all days of a month
      for (let day = startOfMonth.clone(); !day.isAfter(endOfMonth); day.add(1, 'days')) {
        distinctWeeks[day.week()] = true
      }
    
      return Object.keys(distinctWeeks).length;
    }
    

    【讨论】:

      【解决方案9】:
        function weeksInMonth(date = null){
          let firstDay = moment(date).startOf('month');
          let endDay = moment(date).endOf('month');
      
          let weeks = [];
          for (let i = firstDay.week(); i <= endDay.week(); i++){
            weeks.push(i)
          }
      
          return weeks;
        }
      

      【讨论】:

        【解决方案10】:

        这是一个简单的方法(基于a solution posted above):

        const calcWeeksInMonth = (momentDate) => {
          const dateFirst = moment(momentDate).date(1)
          const dateLast = moment(momentDate).date(momentDate.daysInMonth())
          const startWeek = dateFirst.isoWeek()
          const endWeek = dateLast.isoWeek()
        
          if (endWeek < startWeek) {
            // cater to end of year (dec/jan)
            return dateFirst.weeksInYear() - startWeek + 1 + endWeek
          } else {
            return endWeek - startWeek + 1
          }
        }
        

        据我所知,它适用于任何日期,但始终欢迎反馈!

        【讨论】:

        • 2020 年 11 月返回 6 周,而应该是 5 周。
        • @zomars ISO weeks 从星期一开始,所以 2020 年 11 月确实有 6 周。 11 月 1 日是星期日(一周的最后一天),11 月 30 日是星期一(一周的第一天)。如果您更喜欢使用一年中的本地化周,只需在上面的代码中将week 替换为isoWeek。假设您所在的地区是星期天是一周的第一天,这应该会给您 5 周的时间。
        【解决方案11】:

        把它混在一起

        import moment from "moment";
        export const calcWeeksInMonth = date => {
          let weekMonthEnds = moment(date)
            .date(moment(date).daysInMonth())
            .week();
          let weekMonthStarts = moment(date)
            .date(1)
            .week();
        
          return weekMonthEnds < weekMonthStarts
            ? moment(date).isoWeeksInYear() - weekMonthStarts + 1
            : weekMonthEnds - weekMonthStarts + 1;
        };
        

        【讨论】:

          【解决方案12】:
          var month = moment().month();
          var startOfMonth = month.startOf("month");
          var endOfMonth = month.endOf("month");
          var startWeekNumber = startOfMonth.isoWeek();
          var endWeekNumber = endOfMonth.isoWeek();
          var numberOfWeeks = (endWeekNumber - startWeekNumber + 1);
          console.log(numberOfWeeks);
          

          【讨论】:

            【解决方案13】:

            如果您有 selectedDate 值,可以让您有机会检测现在哪个月份处于活动状态:

            private calculateNumberOfWeeks(): number {
                const end = moment(this.selectedDate).endOf('month');
            
                const startDay = moment(this.selectedDate)
                  .startOf('month')
                  .day();
            
                const endDay = end.day();
                const endDate = end.date();
            
                return (startDay - 1 + endDate + (endDay === 0 ? 0 : 7 - endDay)) / 7;
              }
            

            【讨论】:

              【解决方案14】:

              /更新/
              下面的解决方案没有考虑跳到新年。 这是改进的解决方案。

              const getNumberOfWeeksInAMonth = (currentMoment: moment.Moment) => {
                  const currentMomentCopy = cloneDeep(currentMoment)
                  const startOfMonth = currentMomentCopy.startOf('month')
                  const startOfISOWeek = startOfMonth.startOf('isoWeek')
              
                  let numberOfWeeks = 0;
                  
                  do {
                      numberOfWeeks++
                      MomentManager.addWeek(startOfISOWeek)
                  } while (currentMoment.month() === startOfISOWeek.month())
              
                  return numberOfWeeks;
              }
              

              我用momentjs找到了另一个解决方案。

              const getNumberOfWeeksInMonth = (moment: moment.Moment) => {
                const startWeek = moment.startOf('month').isoWeek()
                const endWeek = moment.endOf('month').isoWeek()
                return endWeek - startWeek + 1
              }
              

              【讨论】:

                猜你喜欢
                • 2021-02-16
                • 1970-01-01
                • 1970-01-01
                • 2016-04-21
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2018-01-02
                相关资源
                最近更新 更多