如何使用 moment.js 添加天数,不包括周末?

Posted

技术标签:

【中文标题】如何使用 moment.js 添加天数,不包括周末?【英文标题】:How can I use moment.js to add days, excluding weekends? 【发布时间】:2019-02-24 22:32:55 【问题描述】:

我正在设置一个默认的跟进日期,距当前日期两天,目前有效:

const Notify = moment().add(2, 'days').toDate();

但是,我想排除周末。所以我安装了时刻 WeekDay,但我似乎无法让它在当前日期添加天数。文件要求:

moment().weekday(0)

但是我不能让它在两天后添加。有任何想法吗?

【问题讨论】:

【参考方案1】:
var moment = require("moment")
function addWorkingDay(date, days)
    let daysToAdd = days
    const today = moment(date);
    const nextWeekStart = today.clone().add(1, 'week').weekday(1);
    const weekEnd = today.clone().weekday(5);

    const daysTillWeekEnd = Math.max(0, weekEnd.diff(today, 'days'));
    if(daysTillWeekEnd >= daysToAdd) return today.clone().add(daysToAdd, 'days');
    
    daysToAdd = daysToAdd - daysTillWeekEnd - 1;
    
    return nextWeekStart.add(Math.floor(daysToAdd/5), 'week').add(daysToAdd % 5, 'days')

【讨论】:

【参考方案2】:

这将根据任何开始日期进行,并且没有代价高昂的循环。您计算出您需要跳过的周末天数,然后只用工作日和周末的天数来抵消。

function addWeekdays(year, month, day, numberOfWeekdays) 
    var originalDate = year + '-' + month + '-' + day;
    var futureDate = moment(originalDate);
    var currentDayOfWeek = futureDate.day();            // 0 = Sunday, 1 = Monday, ..., 6 = Saturday
    var numberOfWeekends = Math.floor((currentDayOfWeek + numberOfWeekdays - 1) / 5);   // calculate the number of weekends to skip over

    futureDate.add(numberOfWeekdays + numberOfWeekends * 2, 'days');    // account for the 2 days per weekend

    return futureDate;

【讨论】:

【参考方案3】:

我认为这段代码会更快:

var businessDays = 10;
var days = businessDays + Math.floor((Math.min(moment().day(),5)+businessDays)/6)*2;
moment.add(days, 'days');

【讨论】:

不幸的是,这段代码不起作用。例如,如果在 2020 年 9 月 28 日星期一添加 15 个工作日,我将在 10 月 17 日(星期六)结束。【参考方案4】:

这个解决方案简单易懂,对我来说效果很好:

function addBusinessDays(originalDate, numDaysToAdd) 
  const Sunday = 0;
  const Saturday = 6;
  let daysRemaining = numDaysToAdd;

  const newDate = originalDate.clone();

  while (daysRemaining > 0) 
    newDate.add(1, 'days');
    if (newDate.day() !== Sunday && newDate.day() !== Saturday) 
      daysRemaining--;
    
  

  return newDate;

【讨论】:

【参考方案5】:

您也不能使用外部库并执行以下两个之一的简单功能:

const WEEKEND = [moment().day("Saturday").weekday(), moment().day("Sunday").weekday()]

const addBusinessDays1 = (date, daysToAdd) => 
  var daysAdded = 0,
    momentDate = moment(new Date(date));
  while (daysAdded < daysToAdd) 
    momentDate = momentDate.add(1, 'days');
    if (!WEEKEND.includes(momentDate.weekday())) 
      daysAdded++
    
  

  return momentDate;

console.log(addBusinessDays1(new Date(), 7).format('MM/DD/YYYY'))
console.log(addBusinessDays1('09-20-2018', 3).format('MM/DD/YYYY'))

// This is the somewhat faster version
const addBusinessDays2 = (date, days) => 
  var d = moment(new Date(date)).add(Math.floor(days / 5) * 7, 'd');
  var remaining = days % 5;
  while (remaining) 
    d.add(1, 'd');
    if (d.day() !== 0 && d.day() !== 6)
      remaining--;
  
  return d;
;

console.log(addBusinessDays2(new Date(), 7).format('MM/DD/YYYY'))
console.log(addBusinessDays2('09-20-2018', 3).format('MM/DD/YYYY'))
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"&gt;&lt;/script&gt;

它们从 this post 略微修改,我认为是您必须携带/处理的外部库的一个很好的替代品(假设这是您需要的唯一部分,而不是该库的其他功能)。

【讨论】:

你说“不使用外部库”,然而,你的两个例子都使用moment...我错过了什么吗? 接受的解决方案使用 moment-business-days 而不是 moment 是我的观点。【参考方案6】:

试试:moment-business-days

它应该对你有帮助。

例子:

var momentBusinessDays = require("moment-business-days")

momentBusinessDays('20-09-2018', 'DD-MM-YYYY').businessAdd(3)._d 

结果:

Tue Sep 25 2018 00:00:00 GMT+0530 (IST)

【讨论】:

稍后我将不得不尝试它,在 cmd 中它说它不包含 package.json 文件并出现错误。 npm 错误!代码 ENOLOCAL npm 错误!无法从“>我的目录 检查你是否在项目目录下,你使用的是什么机器,Linux/Mac/Windows? 我是——我在那个错误之后安装了其他几个包,它们工作正常 我使用的是 Windows

以上是关于如何使用 moment.js 添加天数,不包括周末?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Moment.js 格式化日期并减去天数

获取两个日期之间的天数,不包括周末

如何在日期中添加天数,仅考虑工作日(即忽略周末)?

moment.js能判断是不是为节假日吗

如何使用 Moment JS 计算范围之间的给定工作日数?

如何查找两天之间的数据但不包括周末的数据