'How can I use moment.js to add days, excluding weekends?
I'm setting a default follow-up date two days from current date, which currently works:
const Notify = moment().add(2, 'days').toDate();
However, I would like to exclude weekends. So I installed moment WeekDay, but I can't seem to get it to work with adding days to the current date. The documentation calls for:
moment().weekday(0)
But I can't get that to work with adding in two days forward. Any ideas?
Solution 1:[1]
Try: moment-business-days
It should help you.
Example:
var momentBusinessDays = require("moment-business-days")
momentBusinessDays('20-09-2018', 'DD-MM-YYYY').businessAdd(3)._d 
Result:
Tue Sep 25 2018 00:00:00 GMT+0530 (IST)
    					Solution 2:[2]
This solution is simple, easy to follow, and works well for me:
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;
}
    					Solution 3:[3]
You could also not use external lib and do a simple function like one of these two:
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'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
They are slightly modified from this post and I think are a good alternative to external library you have to carry/deal with (assuming this is the only part you need and not other features of that lib).
Solution 4:[4]
This will do it based on any starting date, and without a costly loop. You calculate the number of weekend days you need to skip over, then just offset by the number of weekdays and weekends, together.
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;
}
    					Solution 5:[5]
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')
}
    					Solution 6:[6]
const addWorkingDays = (date: Moment, days: number) => {
  let newDate = date.clone();
  for (let i = 0; i < days; i++) {
    if (newDate.isoWeekday() !== 6 && newDate.isoWeekday() !== 7) {
      newDate = newDate.add(1, "days");
    } else {
      newDate = newDate.add(1, "days");
      i--;
    }
  }
  return newDate.format("YYYY/MM/DD");
};
    					Solution 7:[7]
I think this code will be faster:
var businessDays = 10;
var days = businessDays + Math.floor((Math.min(moment().day(),5)+businessDays)/6)*2;
moment.add(days, 'days');
    					Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source | 
|---|---|
| Solution 1 | Harshal Y. | 
| Solution 2 | zeckdude | 
| Solution 3 | Akrion | 
| Solution 4 | Ryan Loggerythm | 
| Solution 5 | RH-indra Poudel | 
| Solution 6 | mouchin777 | 
| Solution 7 | marc_s | 
