/* 有多种方法可以做到这一点。
您可以将假期和周末的日期放在一个数组中。
通过过滤数组,您可以从
两个日期之间的实际天数,
或在您将工作日添加到开始日期时考虑它们。
当您跨越多年时,它会变得更加复杂
具有不同的假期数组,但这就是计算机的用途... */
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
*/