After revisiting this script, and some modifications, the following is available to allow a user to add a feature that calculates the expected delivery date.
We have UI that defaults search inputs to last business day or a week-ago. Here's something that works both forward and backward.
// add (or subtract) business days to provided date
addBusinessDays = function (startingDate, daysToAdjust) {
var newDate = new Date(startingDate.valueOf()),
businessDaysLeft,
isWeekend,
direction;
// Timezones are scary, let's work with whole-days only
if (daysToAdjust !== parseInt(daysToAdjust, 10)) {
throw new TypeError('addBusinessDays can only adjust by whole days');
}
// short-circuit no work; make direction assignment simpler
if (daysToAdjust === 0) {
return startingDate;
}
direction = daysToAdjust > 0 ? 1 : -1;
// Move the date in the correct direction
// but only count business days toward movement
businessDaysLeft = Math.abs(daysToAdjust);
while (businessDaysLeft) {
newDate.setDate(newDate.getDate() + direction);
isWeekend = newDate.getDay() in {0: 'Sunday', 6: 'Saturday'};
if (!isWeekend) {
businessDaysLeft--;
}
}
return newDate;
};
It would be easy to pass in an optional holidays data structure and adjust for that as well.
However, generating a holidays data structure, well, that will take a little more effort and is specific not only to every country and region, but also to every organization.
I needed something similar but a little different and this is what I came up with.
Holidays are added in an object with one key for each month that has holidays. That key then has an array of days in that month that are considered holidays.
function getDueDate(date) {
var numBusinessDays = 20;
var saturday = 6;
var sunday = 0;
var holidays = {
/* Months are zero-based. 0 = Jan, 11 = Dec */
0: [1, 2],
1: [6],
3: [24],
11: [25, 26]
};
var dayOfWeek = null;
var dayOfMonth = null;
var month = null;
var isWeekday = null;
var monthHolidays = null;
var isHoliday = null;
while (numBusinessDays > 0) {
dayOfWeek = date.getDay();
dayOfMonth = date.getDate();
month = date.getMonth();
isWeekday = dayOfWeek !== saturday && dayOfWeek !== sunday;
monthHolidays = holidays[month];
isHoliday = monthHolidays
? monthHolidays.indexOf(dayOfMonth) > -1
: false;
if (isWeekday && !isHoliday) --numBusinessDays;
date.setDate(dayOfMonth + 1);
}
return date;
}