mcclosa mcclosa - 17 days ago 4
jQuery Question

Subtract days considering weekends

I have a 4 dropdowns that are populated by dates, for example

["23rd December 2016","26th December 2016","27th December 2016","28th December 2016", "29th December 2016"]


In this scenario, I wish to avoid weekends.

The value of each respective dropdown is as follows

- 23rd December 2016
- 26th December 2016
- 27th December 2016
- 28th December 2016


The aim is that if I change the value of the first date from the 23rd ("A Friday") to 26th("A Monday"), the other 3 dates will shift one day to the following values;

- 26th December 2016
- 27th December 2016
- 28th December 2016
- 29th December 2016


This works fine with the following code

addWeekdays: function (date, days) {
date = moment(date); // use a clone
while (days > 0) {
date = date.add(1, 'days');
// decrease "days" only if it's a weekday.
if (date.isoWeekday() !== 6 && date.isoWeekday() !== 7) {
days -= 1;
}
}
return date;
}


The value of each dropdown loops through this function,
date
is the date value of the dropdown and
days
is the number of days difference between the initial date and the new date.

The problem I am having is that if I then try to shift from the 26th back to the 23rd I am unsure how to recreate it so I get the following;

- 23rd December 2016
- 26th December 2016
- 27th December 2016
- 28th December 2016


Basically it's a way to subtract the difference in days exuding weekends, so if the difference in days is 2, I would like to go from Monday to previous Thursday and not to Saturday.

Any help would be greatly appreciated.

Answer

You could make a separate subtractWeekdays function but you'd end up reusing most of the code. The major difference is the 1 in date.add and the while loop skipping when days is negative. We can fix this with a couple minor changes:

  1. Use a pseudo-constant (I named it dayConst for simplicity of example) that will be positive or negative depending on context, instead of a hardcoded 1, when calling date.add
  2. Use a conditional to check if days is negative and if so, modify dayConst to reflect that, and make days positive, so the while loop runs in either case.

function addWeekdays (date, days) {
  // make a 'pseudo-constant' to represent the # used when adding/subtracting days
  var dayConst = 1;
  date = moment(date); // use a clone

  // add functionality for subtraction here
  if (days < 0) {
    dayConst = -1;
    days = -days;
  }

  while (days > 0) {
    // and then dayConst will be -1 if days is negative.
    date = date.add(dayConst, 'days');

    // decrease "days" only if it's a weekday.
    if (date.isoWeekday() !== 6 && date.isoWeekday() !== 7) {
      days -= 1;
    }
  }
  return date;
}

// How I tested them (It's Wednesday Nov 23 here and now, so 3 days +/-        
// is Monday Nov 28 and last Friday Nov 18, respectively)
console.log(addWeekdays(new Date(), 3).format("YYYY MM DD dddd"));
console.log(addWeekdays(new Date(), -3).format("YYYY MM DD dddd"));