如何检测邀约时间与官员已有日程冲突并拦截提交?
检测日程时间段重叠的正确方法
你的现有代码只检查了精确匹配日期和开始时间,这显然无法覆盖时间段重叠的场景——比如用户提议的10:00-11:00AM,刚好落在已有静修会的9:00AM-12:00PM区间内,但因为时间不是精确匹配9:00AM,所以你的查询会漏掉这个冲突。
要解决这个问题,我们需要基于时间段重叠的逻辑来编写查询,核心思路是:判断用户提议的时间段(日期+时间)与数据库中已有日程的时间段是否存在交集。
第一步:理解时间段重叠的判断逻辑
对于两个时间段(日期范围+时间范围),只要满足以下两个条件,就说明存在冲突:
- 日期范围有重叠:已有日程的日期区间与用户提议的日期区间存在交集
- 时间范围有重叠:已有日程的时间区间与用户提议的时间区间存在交集
具体到SQL条件:
- 日期重叠:
已有日程.date_start <= 用户提议的结束日期且已有日程.date_end >= 用户提议的开始日期 - 时间重叠:
已有日程.time < 用户提议的结束时间且已有日程.time_end > 用户提议的开始时间
第二步:改进SQL查询与PHP代码
假设你的用户邀约参数是:
$id:官员ID$user_start_date:邀约开始日期(如2018-01-17)$user_end_date:邀约结束日期(如2018-01-18)$user_time_start:邀约开始时间(如10:00AM)$user_time_end:邀约结束时间(如11:00AM)
安全的查询方式(避免SQL注入)
直接拼接变量到SQL里有注入风险,建议使用MySQLi预处理语句:
// 初始化预处理语句 $stmt = $con->prepare(" SELECT * FROM `events` WHERE `pastor_id` = ? -- 日期范围重叠条件 AND `date_start` <= ? AND `date_end` >= ? -- 时间范围重叠条件 AND `time` < ? AND `time_end` > ? "); // 绑定参数:i=整数(官员ID),s=字符串(日期/时间) $stmt->bind_param("issss", $id, $user_end_date, $user_start_date, $user_time_end, $user_time_start); // 执行查询并获取结果 $stmt->execute(); $result = $stmt->get_result(); $conflict_count = $result->num_rows; // 判断是否存在冲突 if ($conflict_count > 0) { echo "<p>Sorry, this time is occupied. Please select another schedule</p>"; } // 关闭语句和连接(可选,根据你的代码结构) $stmt->close();
针对你案例的测试
用你提供的静修会数据测试:
- 用户提议的日期是2018-01-17至2018-01-18,时间10:00AM-11:00AM
- 数据库中第一条静修会记录的
date_start=2018-01-16,date_end=2018-01-18,time=9:00AM,time_end=12:00PM - 满足
16 <= 18且18 >=17,同时9:00AM <11:00AM且12:00PM>10:00AM,所以会被检测到冲突
额外优化建议
- 统一时间格式:建议将数据库中的
time和time_end字段改为MySQL的TIME类型(24小时制,如09:00:00、12:00:00),这样时间比较会更准确可靠,避免AM/PM格式的解析问题。 - 处理跨天事件:如果未来有跨天的日程(比如从当天18:00到次日02:00),需要调整时间重叠的判断逻辑(比如考虑日期+时间的完整datetime字段),不过当前你的数据模型暂时不需要。
内容的提问来源于stack exchange,提问作者capstone
相关产品推荐
相关产品推荐

