Add business days to a Date
This morning in ##javascript, a visitor asked how to add n business days to a Date instance. Call me a sucker, but I love little tasks like this. Maybe I just get antsy when I smell a potential modulo.
I thought I would be able to find such a function pretty quickly online, but I wanted to write it first, then validate my approach against what I found. Here's what I came up with:
function addBusinessDays(d,n) {
d = new Date(d.getTime());
var day = d.getDay();
d.setDate(
d.getDate() + n +
(day === 6 ? 2 : +!day) +
(Math.floor((n - 1 + (day % 6 || 1)) / 5) * 2));
return d;
}
Not terribly readable, but it works. You could omit the first line if you have no desire to preserve the input Date object. And it is hard coded to assume "business days" are between Monday and Friday. If you wanted to offset the resulting date for holidays, you could maintain an object literal keyed by a serialization of holiday dates, and in the function check against the object, rerunning the algo with n + 1 if a match was found.
Compare and contrast
It turned out after finishing the code, I had little luck finding a comparable function in the wild. Perhaps my search criteria were awful or there's not actually a market for such a function, but my findings were sparse. The closest thing I found was this gargantuan monster. I was surprised that such a function didn't show up in the DateJS lib. Regardless, both collections of functions modify the Date.prototype which I don't do.
So either I need to hone my search skills, or my efforts may have actually been worthwhile.
Here's the function minified…you know, in case you wanted to save 25b over the wire or something:
function addBusinessDays(B,C){B=new Date(B.getTime());var A=B.getDay();B.setDate(B.getDate()+C+(A===6?2:+!A)+(Math.floor((C-1+(A%6||1))/5)*2));return B;}
And a demo page showing a variety of dates and a delta range of -10 to +10.
Update 10/14/2009
I've moved this to a GitHub project and included a couple new versions. One to modify the Date in place and two others that adjust for holidays (some assembly required).