Is there anyway to add day considering only business days without loop\'s like while or for?
It is important the function be flexible to works no count and not count t
There are many questions here already about adding business days, but maybe this isn't an exact duplicate.
There are some rules you need to define, like should adding one day to Saturday be Monday or Tuesday? You seem to like the way moment-business.js does it so the following does the same—adding a day to Sunday or Saturday gives Monday and the passed in Date is modified by the function and returned.
The following moves any weekend date to Sunday for positive or Saturday for negative, then adds "business days" as 7 days for each set of 5. If the start is closer to Saturday (for positive or Sunday for negative) than the number of days to add, (e.g. Thu + 2) then an extra 2 days are added (or subtracted) to get over the weekend.
If the start is Saturday or Sunday, it's moved to Sunday so Saturday plus one day is Monday. If zero days are added, the original date is returned.
Note: I've used the Date constructor to create dates from strings in the test data, but that's only for convenience, it should never be used like that. Always manually parse strings or use a library.
/* Add business days (Monday to Friday) to a date
** If number to add is zero, the original date is returned
** If date is on a weekend, +ve count starts from Sunday, -ve count from Saturday
**
** e.g. Saturday + 1 => Monday
** Sunday + 1 => Monday
** Friday + 1 => Monday
** Saturday - 1 => Friday
** Sunday - 1 => Friday
** Monday - 1 => Friday
** Tuesday - 3 => Thursday
**
** @param {Date} date - Date to add days to. The original date is modified
** @param {number} n - Days to add (+ve to add, -ve to subtract)
** @returns {Date} - The original Date with days added or subtracted
*/
function addBusinessDays(date, n) {
// If adding zero days, just return date
if (n == 0) return date;
// Setup
var weeks = Math[n>0? 'floor' : 'ceil'](n / 5);
var remDays = n % 5;
var dayNum = date.getDay();
var daysToAdd;
// Move date to Sun (+ve) or Sat (-ve) if start is on a weekend
date.setDate(date.getDate() + (n > 0? (dayNum == 6? 1 : 0 ) : (dayNum == 0? -1 : 0)));
// Reset dayNum in case it just moved
dayNum = date.getDay();
// Calculate days to add - deal with +ve and -ve and if days to add is bigger than distance
// to a weekend
var daysToAdd = weeks*7 + (n > 0?(remDays > (5 - dayNum)? 2 : 0) : (-1*remDays >= dayNum? -2 : 0)) + remDays;
date.setDate(date.getDate() + daysToAdd);
return date;
}
['2016-01-01 1', // Fri 1 Jan
'2016-01-01 2', // Fri 1 Jan
'2016-01-02 2', // Sat 2 Jan
'2016-01-05 1', // Tue 5 Jan
'2016-01-05 4', // Tue 5 Jan
'2016-01-05 14', // Tue 5 Jan
'2016-01-02 1', // Sat 2 Jan
'2016-01-03 1' // Sun 3 Jan
].forEach(function(v){
var b = v.split(' ');
document.write(f(new Date(b[0])) + ' ' + b[1] + ' : ' + f(addBusinessDays(new Date(b[0]), b[1])) + '<br>');
});
document.write('<br>Negatives<br><br>');
['2016-01-04 -1', // Mon 4 Jan
'2016-01-04 -2', // Mon 4 Jan
'2016-01-02 -2', // Sat 2 Jan
'2016-01-05 -1', // Tue 5 Jan
'2016-01-05 -4', // Tue 5 Jan
'2016-01-05 -14', // Tue 5 Jan
'2016-01-02 -1', // Sat 2 Jan
'2016-01-03 -1' // Sun 3 Jan
].forEach(function(v){
var b = v.split(' ');
document.write(f(new Date(b[0])) + ' ' + b[1] + ' : ' + f(addBusinessDays(new Date(b[0]), b[1])) + '<br>');
});
function f(d) {
var days = 'Sun Mon Tue Wed Thu Fri Sat'.split(' ');
return d.getFullYear() + '-' + ('0'+(d.getMonth()+1)).slice(-2) + '-' + ('0'+d.getDate()).slice(-2) + ' ' +days[d.getDay()];
}