我需要一个Date.prototype.addBusDays函数 这将取整数作为添加到日期的工作日数。
但是,有两个注意事项:1。周末,2。假期(我想这将是一个要比较的预设数组。如果开始日期和结束日期包含3个假期,那么你将结束日期推出3)
我在网上遇到过一些剧本,我可以想到的一个难题是,让我们说你先解决所有周末,然后你做假期,如果你+1天(由于假期),你的结束日期怎么办?被推迟到周末...<
有什么想法吗? 谢谢!
编辑:
这是我正在开发的调度工具的一部分,这意味着日期将与链接在一起的任务相关联。在任务中添加1天将触发重新计算与其相关的所有内容,可能是数据库中的所有日期。
答案 0 :(得分:5)
function AddWorkingDays(datStartDate, lngNumberOfWorkingDays, blnIncSat, blnIncSun) {
var intWorkingDays = 5;
var intNonWorkingDays = 2;
var intStartDay = datStartDate.getDay(); // 0=Sunday ... 6=Saturday
var intOffset;
var intModifier = 0;
if (blnIncSat) { intWorkingDays++; intNonWorkingDays--; }
if (blnIncSun) { intWorkingDays++; intNonWorkingDays--; }
var newDate = new Date(datStartDate)
if (lngNumberOfWorkingDays >= 0) {
// Moving Forward
if (!blnIncSat && blnIncSun) {
intOffset = intStartDay;
} else {
intOffset = intStartDay - 1;
}
// Special start Saturday rule for 5 day week
if (intStartDay == 6 && !blnIncSat && !blnIncSun) {
intOffset -= 6;
intModifier = 1;
}
} else {
// Moving Backward
if (blnIncSat && !blnIncSun) {
intOffset = intStartDay - 6;
} else {
intOffset = intStartDay - 5;
}
// Special start Sunday rule for 5 day week
if (intStartDay == 0 && !blnIncSat && !blnIncSun) {
intOffset++;
intModifier = 1;
}
}
// ~~ is used to achieve integer division for both positive and negative numbers
newDate.setTime(datStartDate.getTime() + (new Number((~~((lngNumberOfWorkingDays + intOffset) / intWorkingDays) * intNonWorkingDays) + lngNumberOfWorkingDays + intModifier)*86400000));
return newDate;
}
答案 1 :(得分:4)
看看以下实现。来自about.com
addWeekdays = function(date, dd) {
var wks = Math.floor(dd/5);
var dys = dd.mod(5);
var dy = this.getDay();
if (dy === 6 && dys > -1) {
if (dys === 0) {dys-=2; dy+=2;}
dys++; dy -= 6;
}
if (dy === 0 && dys < 1) {
if (dys === 0) {dys+=2; dy-=2;}
dys--; dy += 6;
}
if (dy + dys > 5) dys += 2;
if (dy + dys < 1) dys -= 2;
date.setDate(date.getDate()+wks*7+dys);
}
var date = new Date();
addWeekdays(date, 9);
答案 2 :(得分:1)
我会做一个循环。继续添加天数,直至达到有效的一天。
答案 3 :(得分:1)
(已更新)尽管它确实将递归用于假日处理,但我已经逐步完善了该算法,它似乎很稳定:
holidays = [new Date("2/13/2019"), new Date("2/19/2019")];
function addWorkdays(workdays, startDate) {
//Make adjustments if the start date is on a weekend
let dayOfWeek = startDate.getDay();
let adjustedWorkdays = Math.abs(workdays);
if (0 == dayOfWeek || 6 == dayOfWeek) {
adjustedWorkdays += (Math.abs((dayOfWeek % 5) + Math.sign(workdays)) % 2) + 1;
dayOfWeek = (dayOfWeek - 6) * -1;
}
let endDate = new Date(startDate);
endDate.setDate(endDate.getDate() + (((Math.floor(((workdays >= 0 ? dayOfWeek - 1 : 6 - dayOfWeek) + adjustedWorkdays) / 5) * 2) + adjustedWorkdays) * (workdays < 0 ? -1 : 1)));
//If we cross holidays, recompute our end date accordingly
let numHolidays = holidays.reduce(function(total, holiday) { return (holiday >= Math.min(startDate, endDate) && holiday <= Math.max(startDate, endDate)) ? total + 1 : total; }, 0);
if (numHolidays > 0) {
endDate.setDate(endDate.getDate() + Math.sign(workdays));
return addWorkdays((numHolidays - 1) * Math.sign(workdays), endDate);
} else return endDate;
}
答案 4 :(得分:0)
我扩展了khellendros74对我的项目的回答,该项目需要在日期选择器中禁用星期日和邮寄假日,并在按下按钮时返回两个日期:在日期之后的三个工作日(即非假日和非星期日)在datepicker(id为“calendar”的字段)中挑选,并在datepicker中选择的日期后六个工作日,然后将这两个结果放入几个禁用的输入字段(handDelivered和mailed)。按下按钮调用函数calculateDates。这是代码:
var disabledDates = ['11/11/2015', '11/26/2015', '12/25/2015', '01/01/2016','01/18/2016', '02/15/2016','05/30/2016', '07/04/2016','09/05/2016','10/10/2016','11/11/2016','11/24/2016', '12/26/2016','01/02/2017','01/16/2017', '02/20/2017','05/29/2017', '07/04/2017','09/04/2017','10/09/2017','11/10/2017','11/23/2017', '12/25/2017','01/01/2018','01/15/2018', '02/19/2018','05/28/2018', '07/04/2018','09/03/2018','10/08/2018','11/12/2018','11/22/2018', '12/25/2018','01/01/2019','01/21/2019', '02/18/2019','05/27/2019', '07/04/2019','09/02/2019','10/14/2019','11/11/2019','11/28/2019', '12/25/2019','01/01/2020','01/20/2020', '02/17/2020','05/25/2020', '07/03/2020','09/07/2020','10/11/2020','11/26/2020','11/26/2020', '12/25/2020'];
$(function(){
$('#calendar').datepicker({
dateFormat: 'mm/dd/yy',
beforeShowDay: editDays
});
function editDays(date) {
for (var i = 0; i < disabledDates.length; i++) {
if (new Date(disabledDates[i]).toString() == date.toString() || date.getDay() == 0) {
return [false];
}
}
return [true];
}
});
function calculateDates()
{
if( !$('#calendar').val()){
alert("Please enter a date.");
document.getElementById('calendar').focus();
return false;
}
var dayThreeAdd = 0;
var daySixAdd = 0;
for (var i = 0; i < disabledDates.length; i++) {
var oneDays = AddWorkingDays($('#calendar').val(),1,true,false);
var twoDays = AddWorkingDays($('#calendar').val(),2,true,false);
var threeDays = AddWorkingDays($('#calendar').val(),3,true,false);
var fourDays = AddWorkingDays($('#calendar').val(),4,true,false);
var fiveDays = AddWorkingDays($('#calendar').val(),5,true,false);
var sixDays = AddWorkingDays($('#calendar').val(),6,true,false);
if (new Date(disabledDates[i]).toString() == oneDays.toString()) {
dayThreeAdd++;
daySixAdd++;
}
if (new Date(disabledDates[i]).toString() == twoDays.toString()) {
dayThreeAdd++;
daySixAdd++;
}
if (new Date(disabledDates[i]).toString() == threeDays.toString()) {
dayThreeAdd++;
daySixAdd++;
}
if (new Date(disabledDates[i]).toString() == fourDays.toString()) {
daySixAdd++;
}
if (new Date(disabledDates[i]).toString() == fiveDays.toString()) {
daySixAdd++;
}
if (new Date(disabledDates[i]).toString() == sixDays.toString()) {
daySixAdd++;
}
}
var threeDays = AddWorkingDays($('#calendar').val(),(3 + dayThreeAdd),true,false);
var sixDays = AddWorkingDays($('#calendar').val(),(6 + daySixAdd),true,false);
$('#handDelivered').val((threeDays.getMonth()+1) + '/' + threeDays.getDate() + '/' + (threeDays.getYear()+1900));
$('#mailed').val((sixDays.getMonth()+1) + '/' + sixDays.getDate() + '/' + (sixDays.getYear()+1900));
}
function AddWorkingDays(datStartDate, lngNumberOfWorkingDays, blnIncSat, blnIncSun) {
datStartDate = new Date(datStartDate);
var intWorkingDays = 5;
var intNonWorkingDays = 2;
var intStartDay = datStartDate.getDay(); // 0=Sunday ... 6=Saturday
var intOffset;
var intModifier = 0;
if (blnIncSat) { intWorkingDays++; intNonWorkingDays--; }
if (blnIncSun) { intWorkingDays++; intNonWorkingDays--; }
var newDate = new Date(datStartDate)
if (lngNumberOfWorkingDays >= 0) {
// Moving Forward
if (!blnIncSat && blnIncSun) {
intOffset = intStartDay;
} else {
intOffset = intStartDay - 1;
}
// Special start Saturday rule for 5 day week
if (intStartDay == 6 && !blnIncSat && !blnIncSun) {
intOffset -= 6;
intModifier = 1;
}
} else {
// Moving Backward
if (blnIncSat && !blnIncSun) {
intOffset = intStartDay - 6;
} else {
intOffset = intStartDay - 5;
}
// Special start Sunday rule for 5 day week
if (intStartDay == 0 && !blnIncSat && !blnIncSun) {
intOffset++;
intModifier = 1;
}
}
// ~~ is used to achieve integer division for both positive and negative numbers
newDate.setTime(datStartDate.getTime() + (new Number((~~((lngNumberOfWorkingDays + intOffset) / intWorkingDays) * intNonWorkingDays) + lngNumberOfWorkingDays + intModifier)*86400000));
return newDate;
}
答案 5 :(得分:0)
解决整个问题的简单解决方案;你可以循环过去,以跳过工作日和假期:
Date.prototype.holidays = {
// fill in common holidays
all: [
'0101', // Jan 01
'1225' // Dec 25
],
2016: [
// add year specific holidays
'0104' // Jan 04 2016
],
2017: [
// And so on for other years.
]
};
Date.prototype.addWorkingDays = function(days) {
while (days > 0) {
this.setDate(this.getDate() + 1);
if (!this.isHoliday()) days--;
}
return this;
};
Date.prototype.substractWorkingDays = function(days) {
while (days > 0) {
this.setDate(this.getDate() - 1);
if (!this.isHoliday()) days--;
}
return this;
};
Date.prototype.isHoliday = function() {
function zeroPad(n) {
n |= 0;
return (n < 10 ? '0' : '') + n;
}
// if weekend return true from here it self;
if (this.getDay() == 0 || this.getDay() == 6) {
return true;
}
var day = zeroPad(this.getMonth() + 1) + zeroPad(this.getDate());
// if date is present in the holiday list return true;
return !!~this.holidays.all.indexOf(day) ||
(this.holidays[this.getFullYear()] ?
!!~this.holidays[this.getFullYear()].indexOf(day) : false);
};
// Uasage
var date = new Date('2015-12-31');
date.addWorkingDays(10);
alert(date.toDateString()); // Mon Jan 18 2016
date.substractWorkingDays(10);
alert(date.toDateString()) // Thu Dec 31 2015