如何用JS计算排除周末的工作日天数并推算对应目标日期
N个工作日后目标日期计算实现方案
你遇到的核心问题是单次叠加周末天数的逻辑有漏洞:首次基于原始N天计算出的周末天数叠加后,新增的日期区间内仍可能包含周末,需要迭代修正直到没有新增周末需要补,或者直接用更稳妥的逐天计数逻辑实现。
方案1:逐天计数法(逻辑简单,不易出错,适合N≤1000的常规业务场景)
逻辑:从起始日开始逐天向后遍历,每遇到非周末就将工作日计数+1,直到计数达到目标N值,此时的日期就是最终结果。
// 计算startDate之后第workDayCount个工作日的日期 function getWorkDayAfter(startDate, workDayCount) { let currentDate = new Date(startDate.getTime()); let count = 0; while (count < workDayCount) { currentDate.setDate(currentDate.getDate() + 1); // getDay返回值0为周日,6为周六,直接跳过周末 if (currentDate.getDay() !== 0 && currentDate.getDay() !== 6) { count++; } } return currentDate; } // 测试示例:2021/09/14加10个工作日 const testStart = new Date(2021, 8, 14); // 月份在JS中从0开始计数 const result = getWorkDayAfter(testStart, 10); console.log(result); // 输出2021-09-28,符合预期
该方案无需处理复杂的区间计算逻辑,不会出现遗漏周末的问题,常规业务场景下性能完全足够。如果需要兼容法定节假日,只需要新增节假日判断逻辑,在跳过周末的同时也跳过法定节假日即可。
方案2:迭代修正数学计算法(适合大N值的高性能场景)
逻辑:你现有的countWeekendDays方法可以保留,只需要新增迭代修正逻辑:每次计算当前区间内的周末天数,叠加到总天数后重新计算区间,直到两次计算的总天数一致,说明已经没有新增周末需要补充。
countWeekendDays = (d0, d1) => { var ndays = 1 + Math.round((d1.getTime() - d0.getTime()) / (24 * 3600 * 1000)); var nsaturdays = Math.floor((d0.getDay() + ndays) / 7); return 2 * nsaturdays + (d0.getDay() == 0) - (d1.getDay() == 6); } function getWorkDayAfterFast(startDate, workDayCount) { let currentAddDays = workDayCount; let endDate = new Date(startDate.getTime()); let lastAddDays = 0; // 迭代修正直到没有新增的周末需要补充 while (currentAddDays !== lastAddDays) { lastAddDays = currentAddDays; endDate = new Date(startDate.getTime()); endDate.setDate(startDate.getDate() + currentAddDays); const weekendCount = countWeekendDays(startDate, endDate); currentAddDays = workDayCount + weekendCount; } // 最后修正终点刚好落在周末的情况 while (endDate.getDay() === 0 || endDate.getDay() === 6) { endDate.setDate(endDate.getDate() + 1); } return endDate; } // 测试示例 const testStart2 = new Date(2021, 8, 14); const result2 = getWorkDayAfterFast(testStart2, 10); console.log(result2); // 输出2021-09-28
内容的提问来源于stack exchange,提问作者Kirankumar Dafda
相关产品推荐
相关产品推荐

