How to Calculate business days between two dates in Javascript.
Say
Date 1 : 04-25-2013
Date 2 : 05-10-2013
Holidays : ["04-27-2013","05-03-2013"]
I want total number of days excluding holidays if any exists between these two dates and excluding sundays if any.
I have tried but I can't be able to do it for holidays array.
How to Calculate business days between two dates in Javascript.
Say
Date 1 : 04-25-2013
Date 2 : 05-10-2013
Holidays : ["04-27-2013","05-03-2013"]
I want total number of days excluding holidays if any exists between these two dates and excluding sundays if any.
I have tried but I can't be able to do it for holidays array.
Share edited Apr 25, 2013 at 11:20 Passerby 10.1k2 gold badges36 silver badges52 bronze badges asked Apr 25, 2013 at 11:17 Satish SainiSatish Saini 2,9683 gold badges26 silver badges38 bronze badges 8- 1 possible duplicate of stackoverflow./questions/3464268/… – Linga Commented Apr 25, 2013 at 11:20
- partialclass.blogspot.in/2011/07/… , I hope this could help you. mostly the holidays havent been taken here, you should probably,modify code appropriately – dreamweiver Commented Apr 25, 2013 at 11:21
- @ling.s:Here it is using pure javascript, without Jquery-ui or any lib,so its not a duplicate question . – dreamweiver Commented Apr 25, 2013 at 11:23
- @dreamweiver : This is working fine for weekends but I am not able to do how to remove the national holidays between two dates ? – Satish Saini Commented Apr 25, 2013 at 11:24
- 1 @Sam Khanna : Simple logic would be to store the holidays in a array and pare this array with the final list of days(returned from above code)between start date and end date.So does that ring a bell ;) – dreamweiver Commented Apr 25, 2013 at 11:30
4 Answers
Reset to default 4What you need to do is check if a day is between the two dates you have for your start and end, then subtract a day if true. Then, you need to add a day for each day that isn't day 0
(Sunday) as you go from one date to the other.
This answer uses UTC times so it doesn't have to worry about daylight savings/timezones, etc.
// yyyy-MM-dd hh:mm:ss
var start = new Date('2013-04-25T00:00:00Z'),
end = new Date('2013-05-10T00:00:00Z'),
holiday = [
new Date('2013-04-27T00:00:00Z'),
new Date('2013-05-03T00:00:00Z')
], i = holiday.length,
n_days = 0;
while (i--) { // loop over holidays
if (holiday[i] >= start)
if (holiday[i] <= end)
n_days = n_days - 1; // day holiday within dates
}
while (start <= end) {
if (start.getUTCDay()) n_days = n_days + 1; // not sunday
start.setUTCHours(24); // add a day
}
console.log(n_days); // 12
I didn't check if this is out by one day. You can reduce the memory footprint by taking .valueOf()
for each, except start
as we use actual Date methods for it. Further, you may want to check that the holiday is not a Sunday, too.
An alternate way to get the number of days between two dates, excluding Sundays, is
n_days = (end - start) / 86400000; // time difference in days
i = n_days - start.getUTCDay(); // trim to first Sunday
i = i - i % 7; // trim to last Sunday
n_days = n_days - i / 7; // subtract Sundays
This saves having to loop over each day. After this you would then use the same check as above for removing holidays (remember to re-set i
to holiday.length
).
diff=endDate-startDate;
var holidays=new Array("04-28-2013","05-22-2013","06-28-2013");
idx_holidays=0;
num_holidays=0;
while(idx_holidays < holidays.length)
{
holiday=new Date(holidays[idx_holidays]);
if(diff>holiday-startDate)
num_holidays++;
idx_holidays++;
}
/* There are various ways to do this.
You can put the day of the year of holidays and weekends in an array.
By filtering the array, you can subtract the number of holidays from
the number of actual days that are between two dates,
or account for them when you are adding business days to a starting date.
It gets a little more involved when you span multiple years
with different holiday arrays, but thats what puters are for... */
if(!Array.prototype.filter){
Array.prototype.filter= function(fun, scope){
var T= this, A= [], i= 0, itm, L= T.length;
if(typeof fun== 'function'){
while(i<L){
if(i in T){
itm= T[i];
if(fun.call(scope, itm, i, T)) A[A.length]= itm;
}
++i;
}
}
return A;
}
}
Date.prototype.dayOfYear= function(){
var j1= new Date(this);
j1.setMonth(0,0);
return Math.round((this-j1)/8.64e7);
}
// this covers a few years of federal holidays:
var holidates={
y2012:[1, 2, 16, 51, 149, 186, 247, 282, 316, 317, 327, 360],
y2013:[1, 21, 49, 147, 185, 245, 287, 315, 332, 359],
y2014:[1, 20, 48, 146, 185, 244, 286, 315, 331, 359],
y2015:[1, 19, 47, 145, 184, 185, 250, 285, 315, 330, 359],
y2016:[1, 18, 46, 151, 186, 249, 284, 316, 329, 360, 361],
y2017:[1, 2, 16, 20, 51, 149, 185, 247, 282, 314, 315, 327, 359],
y2018:[1, 15, 50, 148, 185, 246, 281, 315, 316, 326, 359],
y2019:[1, 21, 49, 147, 185, 245, 287, 315, 332, 359],
y2020:[1, 20, 48, 146, 185, 186, 251, 286, 316, 331, 360],
y2021:[1, 18, 20, 46, 151, 185, 186, 249, 284, 315, 329, 358, 359],
y2022:[1, 17, 52, 150, 185, 248, 283, 315, 328, 359, 360, 365],
y2023:[1, 2, 16, 51, 149, 185, 247, 282, 314, 315, 327, 359]
}
// return an array of weekends and holidays for a given year,
// or the current year. Each element is the day of the year,
// Jan 1 is 1.
function getOffdays(y){
if(typeof y!= 'number') y= new Date().getFullYear();
var offdays= [], i= 0, firstwk, lastwk, H= holidates['y'+y].slice(0);
var d= 1, year= new Date(y, 0, 1);
while(year.getDay()!= 0) year.setDate(++d);
firstwk= year.dayOfYear();
year.setMonth(11, 31);
d= 31;
if(year.getDay()== 6) lastwk= year.dayOfYear();
else{
while(year.getDay()!= 0) year.setDate(--d);
lastwk= year.dayOfYear();
}
while(firstwk<= lastwk){
offdays.push(firstwk-1, firstwk);
firstwk+= 7;
}
if(offdays[0]== 0) offdays.shift();
if(H) offdays= offdays.concat(H);
return offdays.sort(function(a, b){
return a-b;
});
}
// expects two dates,
// returns the number of business days between them
function bizDays(day1, day2){
var dayfrom= day1, dayto= day2;
if(day1>day2){
dayto= day1;
dayfrom= day2;
}
var offdays= 0, diff= Math.round((dayto-dayfrom)/8.64e7),
d1= dayfrom.dayOfYear(), d2= dayto.dayOfYear(),
y1= dayfrom.getFullYear(), y2= dayto.getFullYear();
if(y1<y2){
offdays= getOffdays(y1).filter(function(d){
return d>= d1;
}).length;
while(y1+1<y2){
offdays+= getOffdays(++y1).length;
}
offdays+= getOffdays(y1).filter(function(d){
return d<= d2;
}).length;
}
else{
offdays= getOffdays(y1).filter(function(d){
return d>= d1 && d<= d2;
}).length;
}
return diff-offdays;
}
// expects an integer and an optional start date-
// uses the current date if no date is specified.
// returns the date that is biz business days after day1
function bizDaysAfter(biz, day1){
var start= day1 || new Date(),
end= new Date(day1), bdiff;
end.setDate(start.getDate()+biz);
bdiff= biz-bizDays(start, end);
while(bdiff>0){
end.setDate(end.getDate()+bdiff);
bdiff= biz-bizDays(start, end);
}
return end;
}
//Some testing:
var D1= new Date(2013, 3, 25), D2= new Date(2013, 4, 15),
days=14,
s1=D1.toLocaleDateString(), s2=D2.toLocaleDateString();
['Business days between '+ s1+' and\n'+s2+': '+bizDays(D1,D2)+' days.',
days+' business days after '+s1+':\n'+
bizDaysAfter(days,D1).toLocaleDateString()].join('\n\n');
/* returned value: (String)
Business days between Thursday, April 25, 2013 and
Wednesday, May 15, 2013: 14 days.
14 business days after Thursday, April 25, 2013:
Wednesday, May 15, 2013
*/
//days count
var days_count = 0;
//start date
var start = new Date("10/01/2017");
//end date
var end = new Date("10/21/2017");
//holidays array
var date_array = [ new Date('2017-01-26'), new Date('2017-03-13'), new
Date('2017-03-29'), new Date('2017-08-15'), new Date('2017-08-25'), new
Date('2017-10-02'), new Date('2017-10-19'), new Date('2017-12-25')];
while(start <= end){
// 0 = Sunday and 6 = Saturday
if(start.getDay() > 0 && start.getDay() < 6){
days_count = days_count + 1;
for(var dat in date_array){
var a = date_array[dat];
a.setHours(0,0,0,0);
if(a.getTime() == start.getTime()){
days_count = days_count - 1;
}
}
}
var newDate = start.setDate(start.getDate() + 1);
start = new Date(newDate);
}
console.log(days_count);