使用date-fns验证课程时间区间重叠时出现误判问题
问题分析
你当前的核心问题是错误地将课程的两个独立时间段合并成了一个连续的大区间进行重叠判断。
观察你的代码:
const selectedStart = new Date(selectedCourse.start_time_1 * 1000); const selectedEnd = new Date(selectedCourse.end_time_2 * 1000); const courseStart = new Date(c.start_time_1 * 1000); const courseEnd = new Date(c.end_time_2 * 1000);
你把selectedCourse的第一个时间段的开始和第二个时间段的结束拼接成了一个跨多天的超大区间,同理对其他课程也做了同样的处理。比如selectedCourse的两个实际时间段是:
- 时间段1:2024-06-24 09:00 ~ 2024-06-24 11:00
- 时间段2:2024-06-28 09:00 ~ 2024-06-28 11:00
但你却把它当成了2024-06-24 09:00 ~ 2024-06-28 11:00的连续区间,导致任何课程只要在这个大范围内有时间段(比如课程10的时间段是6月25日),都会被误判为重叠。
解决方案
正确的逻辑应该是:分别比较选中课程的两个时间段,与目标课程的两个时间段,只要任意一对时间段重叠,才判定这两门课程时间冲突。
修改后的代码如下:
import { areIntervalsOverlapping } from 'date-fns'; const selectedCourse = { id: 1, name: 'Chemical Engineering', week: 1, capacity: 12, active: 1, start_time_1: 1719241200, end_time_1: 1719248400, start_time_2: 1719586800, end_time_2: 1719594000 }; const courses = [ { id: 1, name: 'Chemical Engineering', week: 1, capacity: 12, active: 1, start_time_1: 1719241200, end_time_1: 1719248400, start_time_2: 1719586800, end_time_2: 1719594000 }, { id: 2, name: 'Mechanical Engineering', week: 1, capacity: 25, active: 1, start_time_1: 1719248400, end_time_1: 1719255600, start_time_2: 1719594000, end_time_2: 1719601200 }, { id: 3, name: 'Industrial Engineering', week: 1, capacity: 25, active: 1, start_time_1: 1719241200, end_time_1: 1719259200, start_time_2: 1719586800, end_time_2: 1719604800 }, { id: 4, name: 'Mechatronics Engineering Group 1', week: 1, capacity: 24, active: 1, start_time_1: 1719241200, end_time_1: 1719248400, start_time_2: 1719586800, end_time_2: 1719594000 }, { id: 5, name: 'Mechatronics Engineering Group 2', week: 1, capacity: 24, active: 1, start_time_1: 1719252000, end_time_1: 1719259200, start_time_2: 1719597600, end_time_2: 1719604800 }, { id: 6, name: 'Fashion Design', week: 1, capacity: 30, active: 1, start_time_1: 1719241200, end_time_1: 1719255600, start_time_2: 1719500400, end_time_2: 1719514800 }, { id: 7, name: 'Financial Engineering', week: 1, capacity: 30, active: 1, start_time_1: 1719241200, end_time_1: 1719255600, start_time_2: 1719500400, end_time_2: 1719514800 }, { id: 8, name: 'Communication, Art and Culture Rally (Morning Group)', week: 1, capacity: 60, active: 1, start_time_1: 1719244800, end_time_1: 1719259200, start_time_2: 1719590400, end_time_2: 1719604800 }, { id: 9, name: 'Communication, Art and Culture Rally (Afternoon Group)', week: 1, capacity: 60, active: 1, start_time_1: 1719262800, end_time_1: 1719277200, start_time_2: 1719608400, end_time_2: 1719622800 }, { id: 10, name: 'Education Sciences', week: 1, capacity: 25, active: 1, start_time_1: 1719331200, end_time_1: 1719342000, start_time_2: 1719504000, end_time_2: 1719514800 }, { id: 11, name: 'Architecture', week: 1, capacity: 60, active: 1, start_time_1: 1719331200, end_time_1: 1719342000, start_time_2: 1719504000, end_time_2: 1719514800 }, { id: 12, name: 'Philosophy and Social Sciences', week: 1, capacity: 25, active: 1, start_time_1: 1719500400, end_time_1: 1719509400, start_time_2: 1719586800, end_time_2: 1719595800 } ]; // 辅助函数:判断两个课程是否存在时间段重叠 const doCoursesOverlap = (courseA, courseB) => { // 转换courseA的两个时间段 const aInterval1 = { start: new Date(courseA.start_time_1 * 1000), end: new Date(courseA.end_time_1 * 1000) }; const aInterval2 = { start: new Date(courseA.start_time_2 * 1000), end: new Date(courseA.end_time_2 * 1000) }; // 转换courseB的两个时间段 const bInterval1 = { start: new Date(courseB.start_time_1 * 1000), end: new Date(courseB.end_time_1 * 1000) }; const bInterval2 = { start: new Date(courseB.start_time_2 * 1000), end: new Date(courseB.end_time_2 * 1000) }; // 检查所有时间段组合是否有重叠 return areIntervalsOverlapping(aInterval1, bInterval1) || areIntervalsOverlapping(aInterval1, bInterval2) || areIntervalsOverlapping(aInterval2, bInterval1) || areIntervalsOverlapping(aInterval2, bInterval2); }; courses.forEach(c => { const isOverlapping = doCoursesOverlap(selectedCourse, c); console.log(`Course ${c.name} (${c.id}) overlaps with selected: ${isOverlapping}`); });
验证结果
修改后,原本被误判的课程(比如ID为10、11的课程)会返回false,因为它们的时间段和选中课程的两个时间段都没有重叠;而真正重叠的课程(比如ID为3、4、8等)会正确返回true。
内容的提问来源于stack exchange,提问作者Ernesto Vazquez
相关产品推荐
相关产品推荐

