代码之家  ›  专栏  ›  技术社区  ›  JDC

片刻js-计算天数-排除工作日

  •  0
  • JDC  · 技术社区  · 7 年前

    情况

    • 我需要计算两个日期之间的天数
    • 并非所有天数都计算在内,只计算特定天数(例如周一、周四、周五)
    • 给定天数的列表是可变的
    • 如果 boolean[] 大小相同 7 ,而数组中的每个位置都将具有 true 如果要计算工作日, false 其他的
    • 职位 0 在数组中是星期天, 1 星期一。。。 6 星期六

    方法

    目前我有一个迭代解决方案:

    function countDays(dateStart, dateEnd, includedDays) {
      let count = 0;
    
      for (let m = moment(dateStart); m.diff(dateEnd, 'days') <= 0; m.add(1, 'days')) {
        if (includedDays[m.weekday()]) {
          count++;
        }
      }
    
      return count;
    }
    
    let count = countDays(moment({
        year: 2018,
        month: 1,
        day: 1
      }),
      moment({
        year: 2018,
        month: 1,
        day: 14
      }), [false, true, true, false, true, false, false]);
    console.log('Daycount: ' + count);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.20.1/moment.min.js"></script>

    问题

    对于较大的差异,这种方法当然需要几秒钟才能完成。 是否有人有更高性能解决方案的想法?

    已经谢谢你了!

    2 回复  |  直到 7 年前
        1
  •  0
  •   ADreNaLiNe-DJ Huy Thành TrÆ°Æ¡ng    7 年前

    您可以使用 recur 的插件 momentjs 可在此处找到: https://github.com/c-trimm/moment-recur

    您必须在 start 以及 end 日期。 这个 includedDays 转换为具有 daysToInclude :

    • map 函数返回 -1 如果数组中的当前项为 false . 它返回 index 如果当前 item true . 了解该索引 0 sunday .
    • filter 函数仅获取大于或等于 0

    然后 recurrence 创建于 开始 终止 对于每个 日期包括 几周中的几天。

    这个 count 通过获取 all 匹配的天数和 length 结果数组的。

    let start = moment({ year: 2018, month: 1, day: 1 });
    let end = moment({ year: 2018, month: 1, day: 14 });
    let includedDays = [false, true, true, false, true, false, false];
    
    let daysToInclude = includedDays.map((item, idx) => item ? idx : -1)
      .filter(item => item >= 0);
      
    let recurrence = moment().recur(start, end)
      .every(daysToInclude).daysOfWeek();
     
    console.log('Days count: ' + recurrence.all().length);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.20.1/moment.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment-recur/1.0.7/moment-recur.min.js"></script>
        2
  •  0
  •   JDC    7 年前

    在以下评论之后 Thomas Kleßen 使用我自己实现解决方案的日期之间的周数。

    代码使用迭代方法进行第一步&上周在范围内,但对介于两者之间的所有内容使用周计数:

    function countDaysIterative(dateStart, dateEnd, includedDays) {
      let count = 0;
    
      for (let m = moment(dateStart); m.diff(dateEnd, 'days') <= 0; m.add(1, 'days')) {
        if (includedDays[m.weekday()]) {
          count++;
        }
      }
    
      return count;
    }
    
    function countDays(dateStart, dateEnd, includedDays) {
      let weekCount = dateEnd.diff(dateStart, 'weeks');
    
      switch (weekCount) {
        case 0:
        case 1:
          return countDaysIterative(dateStart, dateEnd, includedDays);
        default:
          let firstWeekEnd = moment(dateStart).endOf('week');
          let lastWeekStart = moment(dateEnd).startOf('week');
          let firstWeekDayCount = countDaysIterative(dateStart, firstWeekEnd, includedDays);
          let lastWeekDayCount = countDaysIterative(lastWeekStart, dateEnd, includedDays);
          let subWeekCount = lastWeekStart.diff(firstWeekEnd, 'weeks');
          let daysPerWeekCount = includedDays.filter(v => v).length;
          return (subWeekCount * daysPerWeekCount) + firstWeekDayCount + lastWeekDayCount;
      }
    }
    
    let start = moment({
      year: 2018,
      month: 1,
      day: 1
    });
    let end = moment({
      year: 2018,
      month: 1,
      day: 21
    });
    let includedDays = [false, true, true, false, true, false, false];
    
    console.log('Daycount: ' + countDays(start, end, includedDays));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.20.1/moment.min.js"></script>