1

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.

Passerby
  • 9,715
  • 2
  • 33
  • 50
Satish Saini
  • 2,880
  • 3
  • 24
  • 38
  • 1
    possible duplicate of http://stackoverflow.com/questions/3464268/find-day-difference-between-two-dates-excluding-weekend-days – Linga Apr 25 '13 at 11:20
  • http://partialclass.blogspot.in/2011/07/calculating-working-days-between-two.html , I hope this could help you. mostly the holidays havent been taken here, you should probably,modify code appropriately – dreamweiver Apr 25 '13 at 11:21
  • @ling.s:Here it is using pure javascript, without Jquery-ui or any lib,so its not a duplicate question . – dreamweiver Apr 25 '13 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 Apr 25 '13 at 11:24
  • 1
    @Sam Khanna : Simple logic would be to store the holidays in a array and compare 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 Apr 25 '13 at 11:30
  • Is that `holidays` an array of single days or is it used to store date ranges? – Bergi Apr 25 '13 at 11:38
  • It contains all the national holidays. – Satish Saini Apr 25 '13 at 11:40
  • first, store your dates in an unambiguous format... – Alnitak Apr 25 '13 at 12:56

4 Answers4

4

What 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).

Paul S.
  • 64,864
  • 9
  • 122
  • 138
1
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++;
   }
Rob Bednark
  • 25,981
  • 23
  • 80
  • 125
Arup Rakshit
  • 116,827
  • 30
  • 260
  • 317
0

/* 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 computers 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
*/
kennebec
  • 102,654
  • 32
  • 106
  • 127
0
//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);
BKGhanta
  • 11
  • 2