JavaScript优化班次时间扣除缺勤时段逻辑及修复结果错误求助
JavaScript优化班次时间扣除缺勤时段逻辑及修复结果错误求助
看起来你目前面临两个核心问题:
- 当前代码的逻辑有漏洞,漏掉了完全没有被缺勤影响的班次(比如示例里的
19:00-20:00),这就是为什么预期结果里有这个时段,但你的输出里没有; - 想简化当前的嵌套循环实现,但一直没找到合适的方式。
先帮你拆解现有代码的问题:你的代码只处理了和缺勤有交集的班次,完全没被缺勤覆盖的班次根本没被添加到available_times数组里。而且嵌套循环的逻辑是从缺勤出发去匹配班次,很容易遗漏未被影响的部分。
修复+优化后的实现方案
我推荐换一种思路:先把所有班次作为初始可用时间,然后用每个缺勤时段去「切割」当前的可用时间数组。这种方式逻辑更线性,不容易遗漏,也更易读。
完整代码实现
// 工具函数:将时间字符串转成时间戳(基于1970-01-01的毫秒数) const toTimestamp = (timeStr) => Date.parse(`1970/01/01 ${timeStr}`); // 原始数据 const arranged_shifts = [ { start_time: '08:00', finish_time: '10:00' }, { start_time: '10:30', finish_time: '16:00' }, { start_time: '17:00', finish_time: '18:00' }, { start_time: '19:00', finish_time: '20:00' } ]; const absences = [ { start_time: '09:00', finish_time: '09:30' }, { start_time: '11:00', finish_time: '12:30' }, { start_time: '17:30', finish_time: '18:00' } ]; // 初始可用时间:复制所有班次,确保未被影响的班次不会被遗漏 let availableTimes = [...arranged_shifts]; // 遍历每个缺勤,切割当前的可用时间数组 absences.forEach(absence => { const absStart = toTimestamp(absence.start_time); const absEnd = toTimestamp(absence.finish_time); const newAvailable = []; availableTimes.forEach(shift => { const shiftStart = toTimestamp(shift.start_time); const shiftEnd = toTimestamp(shift.finish_time); // 情况1:缺勤和当前班次完全不重叠,直接保留该班次 if (absEnd <= shiftStart || absStart >= shiftEnd) { newAvailable.push(shift); return; } // 情况2:缺勤在班次中间,把班次切成两段 if (absStart > shiftStart && absEnd < shiftEnd) { newAvailable.push({ start_time: shift.start_time, finish_time: absence.start_time }); newAvailable.push({ start_time: absence.finish_time, finish_time: shift.finish_time }); return; } // 情况3:缺勤从班次开头覆盖到中间,只保留后半段 if (absStart <= shiftStart && absEnd < shiftEnd) { newAvailable.push({ start_time: absence.finish_time, finish_time: shift.finish_time }); return; } // 情况4:缺勤从中间覆盖到班次结尾,只保留前半段 if (absStart > shiftStart && absEnd >= shiftEnd) { newAvailable.push({ start_time: shift.start_time, finish_time: absence.start_time }); return; } // 情况5:缺勤完全覆盖整个班次,直接丢弃该班次(无需操作) }); // 更新可用时间为切割后的结果 availableTimes = newAvailable; }); console.log(availableTimes);
代码核心逻辑说明
- 时间统一转换:用
toTimestamp把HH:MM字符串转成时间戳,用数值比较替代字符串比较,逻辑更严谨; - 初始值兜底:一开始就把所有班次加入可用时间,彻底解决了“未被影响的班次被遗漏”的问题;
- 线性切割逻辑:每个缺勤只处理当前的可用时间数组,每一步的结果都基于上一步的状态,避免了嵌套循环的混乱;
- 覆盖所有重叠场景:把缺勤和班次的重叠情况拆分成5种,每种场景单独处理,逻辑清晰无遗漏。
验证结果
运行这段代码后,输出会和你的预期完全一致:
[ { start_time: '08:00', finish_time: '09:00' }, { start_time: '09:30', finish_time: '10:00' }, { start_time: '10:30', finish_time: '11:00' }, { start_time: '12:30', finish_time: '16:00' }, { start_time: '17:00', finish_time: '17:30' }, { start_time: '19:00', finish_time: '20:00' } ]
这种实现方式不仅解决了你的bug,也比原来的嵌套循环更易读、更易维护~
内容来源于stack exchange
相关产品推荐
相关产品推荐

