PHP中结合周常规排班与特殊日期计算下一个可用营业时间
需求背景
我正在开发一个PHP项目,需要计算商家的营业时间,业务包含每周常规排班以及节假日等特殊非标准营业时间。目前已实现特殊营业时间的下一个可用时间计算,但不知道如何从每周常规排班中算出下一个最近的可用营业日期和时间。
现有数据结构
常规营业时间数组
$opening_times = [ ['open' => '09:00:00', 'weekday' => 1], // 周一 ['open' => '09:00:00', 'weekday' => 2], // 周二 ['open' => '09:00:00', 'weekday' => 4], // 周四,周三休息 ['open' => '09:00:00', 'weekday' => 5], // 周五营业时间1 ['open' => '16:00:00', 'weekday' => 5], // 周五营业时间2 ['open' => '09:00:00', 'weekday' => 6], // 周六 ['open' => '09:00:00', 'weekday' => 7], // 周日 ];
特殊营业时间数组(已实现计算逻辑)
$special_opening_times = [ ['date' => '2024-04-24', 'open' => '08:00:00'], ['date' => '2024-04-27', 'open' => '08:00:00'], ['date' => '2024-04-28', 'open' => '09:00:00'], ['date' => '2024-04-30', 'open' => '07:00:00'], ['date' => '2024-04-25', 'open' => '11:00:00'] ];
已完成的特殊时间计算代码
// 参考时间 $reference_datetime = '2024-04-25 10:30:00'; $special_opening_times = [ ['date' => '2024-04-24', 'open' => '08:00:00'], ['date' => '2024-04-27', 'open' => '08:00:00'], ['date' => '2024-04-28', 'open' => '09:00:00'], ['date' => '2024-04-30', 'open' => '07:00:00'], ['date' => '2024-04-25', 'open' => '11:00:00'] // 当日较晚时间 ]; // 日期时间排序函数 function datetime_sort($a, $b) { $a_datetime = strtotime($a['date'] . ' ' . $a['open']); $b_datetime = strtotime($b['date'] . ' ' . $b['open']); return $a_datetime - $b_datetime; } // 使用自定义函数排序日期时间 usort($special_opening_times, 'datetime_sort'); // 存储下一个最近的日期时间 $next_datetime = null; // 遍历已排序的日期时间,找到下一个最近的日期时间 foreach ($special_opening_times as $date_array) { $current_datetime = strtotime($date_array['date'] . ' ' . $date_array['open']); if (strtotime($reference_datetime) < $current_datetime) { $next_datetime = $date_array['date'] . ' ' . $date_array['open']; break; } } // 输出下一个最近的日期时间 echo $next_datetime;
解决方案:常规营业时间的下一个可用时间计算
实现思路
- 将参考时间转换为
DateTime对象,简化日期计算与比较逻辑。 - 从参考时间当天开始,依次检查未来7天(覆盖一整周排班):
- 获取当天的星期几(PHP中
DateTime::format('N')返回1=周一到7=周日,与常规数组的weekday字段匹配)。 - 筛选出该星期几对应的所有营业时间并按时间排序。
- 检查这些时间是否晚于参考时间,取最早的符合条件的时间作为结果。
- 若当天无可用时间,继续检查下一天。
- 获取当天的星期几(PHP中
代码实现
// 参考时间 $reference_datetime = '2024-04-25 10:30:00'; $ref_dt = new DateTime($reference_datetime); // 常规营业时间数组 $opening_times = [ ['open' => '09:00:00', 'weekday' => 1], // 周一 ['open' => '09:00:00', 'weekday' => 2], // 周二 ['open' => '09:00:00', 'weekday' => 4], // 周四,周三休息 ['open' => '09:00:00', 'weekday' => 5], // 周五营业时间1 ['open' => '16:00:00', 'weekday' => 5], // 周五营业时间2 ['open' => '09:00:00', 'weekday' => 6], // 周六 ['open' => '09:00:00', 'weekday' => 7], // 周日 ]; // 存储下一个常规营业时间 $next_regular_datetime = null; // 最多检查未来7天(覆盖一整周) for ($i = 0; $i < 7; $i++) { // 计算当前要检查的日期 $check_dt = clone $ref_dt; $check_dt->modify("+$i day"); // 获取当天的星期几(1=周一,7=周日) $current_weekday = (int)$check_dt->format('N'); // 筛选出当天的所有营业时间 $day_openings = array_filter($opening_times, function($item) use ($current_weekday) { return $item['weekday'] === $current_weekday; }); // 如果当天没有营业时间,跳过 if (empty($day_openings)) { continue; } // 将当天的营业时间按时间排序 usort($day_openings, function($a, $b) { return strtotime($a['open']) - strtotime($b['open']); }); // 检查每个营业时间是否晚于参考时间 foreach ($day_openings as $opening) { $opening_dt = clone $check_dt; list($hour, $min, $sec) = explode(':', $opening['open']); $opening_dt->setTime((int)$hour, (int)$min, (int)$sec); // 如果该时间晚于参考时间,记录并退出循环 if ($opening_dt > $ref_dt) { $next_regular_datetime = $opening_dt->format('Y-m-d H:i:s'); break 2; // 跳出两层循环 } } } // 输出结果 echo $next_regular_datetime; // 示例中会输出:2024-04-25 16:00:00
代码说明
- 用
DateTime类处理日期时间,避免手动操作时间戳的复杂逻辑,可读性更强且不易出错。 - 循环检查7天确保覆盖完整的常规排班周期,不会遗漏后续可用时间。
- 对每日营业时间排序后优先选择最早的可用时间,符合“下一个最近”的需求。
- 找到符合条件的时间后直接跳出所有循环,提升执行效率。
内容的提问来源于stack exchange,提问作者tony
相关产品推荐
相关产品推荐

