# Add days to date while ignoring weekends and holidays - possible?

I came across a function that adds a specified number of business days to a given date and it works beautifully. My question is, is it possible to account for holidays in this? I don’t mind hardcoding them at all, but I’m not nearly intelligent enough to even begin with the logic. I’ve looked at this code for quite a while, and I’m really not sure if it’s even possible. Your assistance is GREATLY appreciated!

``````function add_business_days(days) {
var now = new Date('04/25/2008');
var dayOfTheWeek = now.getDay();
var calendarDays = days;
var deliveryDay = dayOfTheWeek + days;
if (deliveryDay >= 6) {
//deduct this-week days
days -= 6 - dayOfTheWeek;
//count this coming weekend
calendarDays += 2;
//how many whole weeks?
deliveryWeeks = Math.floor(days / 5);
//two days per weekend per week
calendarDays += deliveryWeeks * 2;
}
now.setTime(now.getTime() + calendarDays * 24 * 60 * 60 * 1000);
return now;
}
``````

The holidays are the ones currently in effect in the US-
minus Easter, which is always on a Sunday and doesn’t
need to be accounted for in your code.
Most of the code is figuring out which day of the year
is the fourth Thursday in November, and so on.

You should be able to use what you have with this to add the business days you need.

``````var Bday= {
bizDays: function(d1,d2){
d1= new Date(d1);
d2= new Date(d2);
var interval= Math.abs(d1-d2);
var days= Math.floor(interval/8.46e7);
var tem= days&#37;7;
var weeks= Math.floor(days/7);
var temp= tem;
var wd1= d1.getDay();
var wd2= d2.getDay();
if(wd1== 6) tem-= 2;
else if(wd1== 0) tem-= 1;
if(wd2== 0) tem-= 1;
var diff= Bday.holBetween(d1,d2);
tem-= diff[0];
return weeks*5+tem;;
},
getdayOffset:function(y,wot){
var month,count,D,temp;
if(wot.length>3){
if(y< wot[3]) return false;
if(wot[4] && y >wot[4]) return false;
}
day= wot[1];
if(wot[0]== 'last'){
month= wot[2];
count= -1;
}
else{
count= wot[0]-1;
month= wot[2]-1;
}
D= new Date(y,month,1);
while(D.getDay()!= day) D.setDate(D.getDate()+1);
D.setDate((7*count)+D.getDate());
return [D.getMonth(),D.getDate()];
},
getHolidays: function(year){
year= year || new Date().getFullYear();
if(Bday.holidays['y_'+year]) return Bday.holidays['y_'+year];

var hol= [ //months are indexed by +1
['New Years Day',[1,1]],
['Independence Day',[7,4]],
['Christmas Day',[12,25]],
['Thanksgiving Day', [4,4,11]],
['Columbus Day',[2,1,10]],
['Mothers\\' Day',[2,0,5]],
['Fathers\\' Day',[3,0,6]],
['Labor Day',[1,1,9]],
['Martin Luther King Day',[3,1,1]],
['Presidents Day',[3,1,2]],
['Memorial Day',['last',1,5]],
['Veterans\\' Day',[11, 11]]
]
if(year<1796)hol= [];
else{
var I= year-1937;
if(I>0 && I%4== 0) hol.push(['Inauguration Day', [1,20]]);
}
if(year<1900)hol.splice(4);
if(year<1861)hol.splice(3);
return Bday.setHolArray(year,hol)
},
holBetween:function (d1,d2){
var A= [],tem,day,count= 0;
while(d2-d1> 0){
d1.setDate(d1.getDate()+1);
tem= d1.isHoliday();
if(!tem) continue;
A.push(tem);
day= d1.getDay();
if(day!= 0 && day!= 6)++count;
}
return [count,A];
},
holidays:{},
setHolArray: function(y,hol){
var L= hol.length;
var A= [],name,temp;
for(var i= 0; i< 12; i++) A[i]= [];
for(var i= 0; i< L; i++){
name= hol[i][0];
temp= hol[i][1];
if(!temp) continue;
if(temp.length >= 3){
temp= Bday.getdayOffset(y,temp);
}
else temp[0]-= 1;
A[temp[0]][temp[1]]= name;
}
return A;
}
}
Date.prototype.isHoliday= function(){
var y= this.getFullYear();
var ys= 'y_'+y;
if(!Bday.holidays[ys]){
Bday.holidays[ys]= Bday.getHolidays(y);
}
var hol= Bday.holidays[ys];
var m= this.getMonth();
var d= this.getDate();
if(hol[m] && hol[m][d])return hol[m][d];
return false;
}
``````

//count of business days until Christmas
//pass the start date and end date arguments
//as either date objects or timestamps

var d1=new Date(2008,3,10);
var d2=Date.parse(‘12,25,2008’);

Thank you for your reply, however I seem to be having trouble getting this to work correctly. When I first tried running your code, d2 was coming back as not a number. I then changed the syntax of the date to ‘4/28/2008’ at which point it alerted “12”. While that seems close, the correct answer is actually 11 when using today’s date - unless I’m missing something.

I then thought I’d be clever by simply subtracting one from d2, but on certain dates, that threw the count off.

Like I said, I could be missing something here and I’d be very grateful if you could help me out a little further. Thanks again!

Date.parse(‘12/25/2008’)
You are correct- IE does require the ‘/’ format for digits, though it will correctly interpret text with commas-
Date.parse(‘April 10,2008’).
Add this method to the mix-

``````Date.prototype.addbizDays=function(n){
var D=this;
var num=Math.abs(n);
var tem,count=0;
var dir= (n<0)? -1: 1;
while(count< num){
D= new Date(D.setDate(D.getDate()+dir));
if(D.isHoliday())continue;
tem=D.getDay();
if(tem!=0 && tem!=6) ++count;
}
return D;
}
``````

//April doesn’t have any holidays, so I’ll use November-
var D=new Date(2008,10,15)

Wow - this worked PERFECTLY under every possible test I put it through. I have to admit, I don’t fully understand the code, but I do know enough to alter the holidays and use the results in the rest of my code.

I can’t thank you enough for your help, but if you have a PayPal account, please PM me your PayPal email address and I will send a small tip your way.

Thanks so much!

You shouldn’t have to alter the holidays, unless you need to add or remove any.
They will calculate the correct day for any year since each holiday became official.
Look closely at the holiday array- if there is a third entry in the holiday’s item,
the holiday is calculated with getdayOffset, rather than as a static date

[‘Christmas Day’,[12,25]]// Christmas is always December 25
[‘Thanksgiving Day’, [4,4,11]]//Thanksgiving is the fourth thursday in November