【问题标题】:How to calculate Number of 'Working days' between two dates in Javascript using moment.js?如何使用moment.js计算Javascript中两个日期之间的“工作日”数?
【发布时间】:2015-04-10 02:23:01
【问题描述】:

如何使用 moment.js 在 JavaScript 中计算两个日期之间的工作日数。我有一个计算这些天的工作公式,但该公式并不满足所有条件:

这是我的代码:

var start= moment(data[x].start_date);
                var end= moment(data[x].est_end_date);
                var difference= end.diff(start, 'days');
                var workingDays= Math.round((difference/7)*5);
//data[x] is for iterating over a loop

我在这里每 7 天得到 5 天,因为星期六和星期日被视为非工作日,但是如果从星期日或星期六开始计算天数,则此公式将失败。

请任何人在这方面提供帮助,必须进行必要的更改以避免此问题。

【问题讨论】:

    标签: javascript date formula momentjs


    【解决方案1】:

    只需将其分为 3 部分.. 第一周、上周和中间的部分,如下所示:

    function workday_count(start,end) {
      var first = start.clone().endOf('week'); // end of first week
      var last = end.clone().startOf('week'); // start of last week
      var days = last.diff(first,'days') * 5 / 7; // this will always multiply of 7
      var wfirst = first.day() - start.day(); // check first week
      if(start.day() == 0) --wfirst; // -1 if start with sunday 
      var wlast = end.day() - last.day(); // check last week
      if(end.day() == 6) --wlast; // -1 if end with saturday
      return wfirst + Math.floor(days) + wlast; // get the total
    } //              ^ EDIT: if days count less than 7 so no decimal point
    

    测试代码

    var ftest = {date:'2015-02-0',start:1,end:7};
    var ltest = {date:'2015-02-2',start:2,end:8};
    var f = 'YYYY-MM-DD';
    for(var z=ftest.start; z<=ftest.end; ++z) {
      var start = moment(ftest.date + z);
      for(var y=ltest.start; y<=ltest.end; ++y) {
        var end = moment(ltest.date + y);
        var wd = workday_count(start,end);
        console.log('from: '+start.format(f),'to: '+end.format(f),'is '+wd+' workday(s)');
      }
    }
    

    测试代码的输出:

    from: 2015-02-01 to: 2015-02-22 is 15 workday(s)
    from: 2015-02-01 to: 2015-02-23 is 16 workday(s)
    from: 2015-02-01 to: 2015-02-24 is 17 workday(s)
    from: 2015-02-01 to: 2015-02-25 is 18 workday(s)
    from: 2015-02-01 to: 2015-02-26 is 19 workday(s)
    from: 2015-02-01 to: 2015-02-27 is 20 workday(s)
    from: 2015-02-01 to: 2015-02-28 is 20 workday(s)
    from: 2015-02-02 to: 2015-02-22 is 15 workday(s)
    from: 2015-02-02 to: 2015-02-23 is 16 workday(s)
    from: 2015-02-02 to: 2015-02-24 is 17 workday(s)
    from: 2015-02-02 to: 2015-02-25 is 18 workday(s)
    from: 2015-02-02 to: 2015-02-26 is 19 workday(s)
    from: 2015-02-02 to: 2015-02-27 is 20 workday(s)
    from: 2015-02-02 to: 2015-02-28 is 20 workday(s)
    from: 2015-02-03 to: 2015-02-22 is 14 workday(s)
    from: 2015-02-03 to: 2015-02-23 is 15 workday(s)
    from: 2015-02-03 to: 2015-02-24 is 16 workday(s)
    from: 2015-02-03 to: 2015-02-25 is 17 workday(s)
    from: 2015-02-03 to: 2015-02-26 is 18 workday(s)
    from: 2015-02-03 to: 2015-02-27 is 19 workday(s)
    from: 2015-02-03 to: 2015-02-28 is 19 workday(s)
    from: 2015-02-04 to: 2015-02-22 is 13 workday(s)
    from: 2015-02-04 to: 2015-02-23 is 14 workday(s)
    from: 2015-02-04 to: 2015-02-24 is 15 workday(s)
    from: 2015-02-04 to: 2015-02-25 is 16 workday(s)
    from: 2015-02-04 to: 2015-02-26 is 17 workday(s)
    from: 2015-02-04 to: 2015-02-27 is 18 workday(s)
    from: 2015-02-04 to: 2015-02-28 is 18 workday(s)
    from: 2015-02-05 to: 2015-02-22 is 12 workday(s)
    from: 2015-02-05 to: 2015-02-23 is 13 workday(s)
    from: 2015-02-05 to: 2015-02-24 is 14 workday(s)
    from: 2015-02-05 to: 2015-02-25 is 15 workday(s)
    from: 2015-02-05 to: 2015-02-26 is 16 workday(s)
    from: 2015-02-05 to: 2015-02-27 is 17 workday(s)
    from: 2015-02-05 to: 2015-02-28 is 17 workday(s)
    from: 2015-02-06 to: 2015-02-22 is 11 workday(s)
    from: 2015-02-06 to: 2015-02-23 is 12 workday(s)
    from: 2015-02-06 to: 2015-02-24 is 13 workday(s)
    from: 2015-02-06 to: 2015-02-25 is 14 workday(s)
    from: 2015-02-06 to: 2015-02-26 is 15 workday(s)
    from: 2015-02-06 to: 2015-02-27 is 16 workday(s)
    from: 2015-02-06 to: 2015-02-28 is 16 workday(s)
    from: 2015-02-07 to: 2015-02-22 is 10 workday(s)
    from: 2015-02-07 to: 2015-02-23 is 11 workday(s)
    from: 2015-02-07 to: 2015-02-24 is 12 workday(s)
    from: 2015-02-07 to: 2015-02-25 is 13 workday(s)
    from: 2015-02-07 to: 2015-02-26 is 14 workday(s)
    from: 2015-02-07 to: 2015-02-27 is 15 workday(s)
    from: 2015-02-07 to: 2015-02-28 is 15 workday(s)
    

    【讨论】:

    • 对于 5 天的日期范围,它给出 5.7 天。
    • 其实对于小于 7 天的日期范围,该值是十进制数字。
    • 我遇到了同样的问题。这是由于一周开始和结束之间的夏令时差异。修复如下。
    • 只需添加Math.floor(days) 即可解决问题'__')感谢您发现这一点
    【解决方案2】:

    如果日子在同一周(例如从太阳到星期六),我发现 kokizzu 的答案不起作用,所以改为解决这个问题:

        function calcBusinessDays(startDate, endDate) { 
          var day = moment(startDate);
          var businessDays = 0;
    
          while (day.isSameOrBefore(endDate,'day')) {
            if (day.day()!=0 && day.day()!=6) businessDays++;
            day.add(1,'d');
          }
          return businessDays;
        }
    

    【讨论】:

    • 对我来说可以在多个月内正常工作...也许您可以分享您的代码/错误?
    【解决方案3】:

    我已对 Kokizzu 的回答进行了改编,以解决夏令时问题。在巴西时区 (GMT -3) 中,17/10/2017 和 18/10/2017 之间的差异是 -2.71 而不是 2。

    本周开始时间是 15/10/2017 00:00 UTC 或 14/10/2017 21:00-03:00

    本周结束时间为 22/10/2017 00:00 UTC 或 21/10/2017 22:00-02:00(夏令时)

    因此,“first”和“last”变量之间的天数之差不是 7,而是 6(或 8,具体取决于您的时区)。

    修复的代码如下:

    start = moment(start).utc().add(start.utcOffset(), 'm'); // Ignore timezones
    end = moment(end).utc().add(end.utcOffset(), 'm'); // Ignore timezones
    
    var first = start.clone().endOf('week'); // end of first week
    var last = end.clone().startOf('week'); // start of last week
    
    // Fixing Summer Time problems
    firstCorrection = moment(first).utc().add(60, 'm').toDate(); //
    var days = last.diff(firstCorrection,'days') * 5 / 7; // this will always multiply of 7
    
    var wfirst = first.day() - start.day(); // check first week
    if(start.day() == 0) --wfirst; // -1 if start with sunday
    var wlast = end.day() - last.day(); // check last week
    if(end.day() == 6) --wlast; // -1 if end with saturday
    return wfirst + days + wlast; // get the total (subtract holidays if needed)
    

    【讨论】:

      【解决方案4】:

      我使用一个简单的函数来实现这一点。也许不是最有效的,但它确实有效。它不需要 Moment.js。它只是 Javascript。

      function getNumWorkDays(startDate, endDate) {
          var numWorkDays = 0;
          var currentDate = new Date(startDate);
          while (currentDate <= endDate) {
              // Skips Sunday and Saturday
              if (currentDate.getDay() !== 0 && currentDate.getDay() !== 6) {
                  numWorkDays++;
              }
              currentDate = currentDate.addDays(1);
          }
          return numWorkDays;
      }
      

      addDays,我使用如下函数:

      Date.prototype.addDays = function (days) {
          var date = new Date(this.valueOf());
          date.setDate(date.getDate() + days);
          return date;
      };
      

      【讨论】:

        【解决方案5】:

        你可以试试这个(没有循环):

          function getBusinessDays(endDate, startDate) {
            var lastDay = moment(endDate);
            var firstDay = moment(startDate);
            let calcBusinessDays = 1 + (lastDay.diff(firstDay, 'days') * 5 -
              (firstDay.day() - lastDay.day()) * 2) / 7;
        
            if (lastDay.day() == 6) calcBusinessDays--;//SAT
            if (firstDay.day() == 0) calcBusinessDays--;//SUN
        
            return calcBusinessDays;
          }
        

        Original Source

        【讨论】:

          【解决方案6】:

          通过使用momentjs,可以这样:

          private calculateWorkdays(startDate: Date, endDate: Date): number {
          // + 1 cause diff returns the difference between two moments, in this case the day itself should be included.
          
          const totalDays: number = moment(endDate).diff(moment(startDate), 'days') + 1;
          const dayOfWeek = moment(startDate).isoWeekday();
          let totalWorkdays = 0;
          
          for (let i = dayOfWeek; i < totalDays + dayOfWeek; i++) {
              if (i % 7 !== 6 && i % 7 !== 0) {
                totalWorkdays++;
              }
            }
            return totalWorkdays;
          }
          

          【讨论】:

          • 欢迎来到 SO! stackoverflow.com 上只允许使用英语回答。欲了解更多信息,请阅读this post
          【解决方案7】:

          我已经使用了一个有用的库 moment-business-days 加上 moment

          NPM Link of Moment-business-days

          NPM Link of Moment

          之间的工作日示例

          const diff = moment('05-15-2017', 'MM-DD-YYYY').businessDiff(moment('05-08-2017','MM-DD-YYYY'));
          // diff = 5
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-08-03
            • 1970-01-01
            • 2010-09-20
            • 1970-01-01
            相关资源
            最近更新 更多