如何用JavaScript计算符合工作日规则的结束日期?
计算排除周末的工作结束日期
需求说明
- 输入:起始日期、工作时长(小时数)
- 输出:实际工作日的结束日期(排除周六和周日)
- 规则:
- 工作周为周一至周五,共5天
- 每日工作时长8小时
现有问题
当前实现仅能正确处理整周的情况,非整周场景计算结果有误,代码如下:
function formatDate(date) { var d = new Date(date), month = '' + (d.getMonth() + 1), day = '' + d.getDate(), year = d.getFullYear(); if (month.length < 2) month = '0' + month; if (day.length < 2) day = '0' + day; return [year, month, day].join('-'); } $('#startTimeProject,#doTimeProject').change(function() { var startTime = $('#startTimeProject').val(); var doTime = $('#doTimeProject').val(); if (doTime == null) { return; } const d = new Date(startTime); var currentDay = d.getDay(); startTime = new Date(startTime); if (currentDay == 0) { startTime.setDate(startTime.getDate() + 1); } if (currentDay == 6) { startTime.setDate(startTime.getDate() + 2); } startTime = Date.parse(startTime); $('#startTimeProject').val(formatDate(startTime)); var numberWeek = Math.floor(doTime / 40); if (numberWeek >= 1) { doTime = Number(doTime) + numberWeek * 16; } var dayTime = Math.ceil(doTime / 8); var endTime = new Date(startTime); endTime.setDate(endTime.getDate() + dayTime); endTime = Date.parse(endTime); $('#endTimeProject').val(formatDate(endTime)); })
解决方案
核心思路是逐天迭代,跳过周末,累计工作日天数,直到达到所需的工作日总数,能覆盖所有整周/非整周场景。
修正后的代码
function formatDate(date) { const d = new Date(date); const month = String(d.getMonth() + 1).padStart(2, '0'); const day = String(d.getDate()).padStart(2, '0'); const year = d.getFullYear(); return `${year}-${month}-${day}`; } function getEndWorkDate(startDate, workHours) { const dailyHours = 8; const workDaysNeeded = Math.ceil(workHours / dailyHours); const currentDate = new Date(startDate); // 将起始日期调整为工作日 const dayOfWeek = currentDate.getDay(); if (dayOfWeek === 0) { // 周日调整到周一 currentDate.setDate(currentDate.getDate() + 1); } else if (dayOfWeek === 6) { // 周六调整到周一 currentDate.setDate(currentDate.getDate() + 2); } let workDaysCounted = 0; // 循环累计工作日,跳过周末 while (workDaysCounted < workDaysNeeded) { const currentDay = currentDate.getDay(); // 仅统计周一至周五 if (currentDay !== 0 && currentDay !== 6) { workDaysCounted++; // 达到目标天数时停止循环 if (workDaysCounted === workDaysNeeded) break; } currentDate.setDate(currentDate.getDate() + 1); } return currentDate; } $('#startTimeProject,#doTimeProject').change(function() { const startTime = $('#startTimeProject').val(); const doTime = $('#doTimeProject').val(); if (!doTime) return; // 调整起始日期为工作日并更新输入框 const adjustedStartDate = new Date(startTime); const dayOfWeek = adjustedStartDate.getDay(); if (dayOfWeek === 0) { adjustedStartDate.setDate(adjustedStartDate.getDate() + 1); } else if (dayOfWeek === 6) { adjustedStartDate.setDate(adjustedStartDate.getDate() + 2); } $('#startTimeProject').val(formatDate(adjustedStartDate)); // 计算并设置结束日期 const endDate = getEndWorkDate(adjustedStartDate, Number(doTime)); $('#endTimeProject').val(formatDate(endDate)); })
关键说明
- 日期格式化优化:使用
padStart简化补零逻辑,代码更简洁。 - 核心计算逻辑:
- 先将起始日期调整为工作日,避免从周末开始计算的误差。
- 通过循环逐天检查日期类型,仅统计周一至周五的工作日,直到累计够所需天数,彻底解决非整周场景的计算问题。
- 事件处理拆分:将日期调整和结束日期计算逻辑拆分,代码可读性更强。
内容的提问来源于stack exchange,提问作者unLimit
相关产品推荐
相关产品推荐

