需求分析
当我们有一个需求,内容是给一个健身房门店设置营业时间
要求限制客户只能在该门店营业时间范围内进行预约健身操作
面临情况
24小时营业
营业时间 == 结业时间
营业时间不跨日
营业时间 < 结业时间
营业时间跨日
营业时间 > 结业时间
分析业务并实现
(xx:xx 这种不带日期的时间称为“时刻”或“时间点)
我们目前知道的是,客户会挑选指定时间段(例 :2023-03-24 9:00 ~ 2023-03-24 10:30)来进行健身门店的预约操作
那么在我们现在所面临的三种情况中,可以知道 24小时营业 与 营业时间不跨日这两种情况可以说是最简单解决的,
唯一麻烦的是营业时间跨日的问题
解决代码如下:
/**
* 判断当前时间是否在门店营业时间内
*
* @param array $store_time 门店营业范围[开业时间,结业时间]
* @param array $datetime 客户预约门店时间范围[开始时间,结束时间]
* @return bool
*/
function isStoreBusinessHours(array $store_time, array $datetime): bool
{
//先拿到开业结业的时间点,把他们转成当日的时间点时间戳,进行对比
$open_time_TIM = strtotime($store_time[0]); //开业时间点时间戳
$close_time_TIM = strtotime($store_time[1]); //结业时间点时间戳
//24小时营业
if ($open_time_TIM == $close_time_TIM) {
return true;
}
$start_datetime = strtotime($datetime[0]); //客户起始时间(时间戳)
$end_datetime = strtotime($datetime[1]); //客户结束时间(时间戳)
//营业时间无跨日
if ($open_time_TIM < $close_time_TIM) {
//此时不能继续使用$open_time_TIM与$close_time_TIM进行范围比较
//因为$open_time_TIM与$close_time_TIM是用来直接转换为今日的时间点进行判断门店营业类型的
//如果客户预约的时间不是今日,是明天或者后天,就不能继续使用
//这时候我们需要将门店营业的时间点与客户的预约时间的日期(不带时间点)来合并成一个完整的日期时间
//例:营业时间点 08:00 - 12:00 客户预约的日期时间 2023-03-24 8:30 ~ 2023-03-24 09:00
//第一步:从客户的起始日期时间中提取 2023-03-24 的日期,并转换为时间戳
//第二步:将客户的起始日期时间的时间戳与门店营业时间点(无日期的时间)合并在一起成为门店开业/结业日期时间时间戳
$date_TIM = strtotime(date('Y-m-d', $start_datetime)); //客户起始时间的日期时间戳提取
//门店开业/结业日期时间时间戳 = 客户起始预约时间时间戳 + 开业/结业无日期时间的时间戳
//(为什么只用起始预约时间戳?因为门店营业时间为不跨日,客户若跨日了就直接不允许预约了)
$open_datetime = getDatetimeTimestamp($date_TIM, $store_time[0]);
$close_datetime = getDatetimeTimestamp($date_TIM, $store_time[1]);
if ($start_datetime >= $open_datetime && $end_datetime <= $close_datetime) {
return true;
}
}
//跨日营业
if ($open_time_TIM > $close_time_TIM) {
//先获取到当前时间的年月日,按照不同跨日结业时间,再将门店开业/结业的无日期的时间合并回来,再进行时间戳对比
//解释:
//假如门店营业营业时间为跨日营业 08:00 ~ 02:00
//情况一:客户预约时间为 2023-03-25 08:30 ~ 2023-03-26 02:00 属于在当日的跨日营业时间范围
//情况二:客户预约时间为 2023-03-25 00:00 ~ 2023-03-25 02:00 属于在昨日的跨日营业时间范围
//今跨日结业时间
$date_TIM = strtotime(date('Y-m-d', $start_datetime));
$cross_date_TIM = strtotime('+1 day', strtotime(date('Y-m-d', $start_datetime)));
$open_datetime = getDatetimeTimestamp($date_TIM, $store_time[0]); //今跨日营业的起始时间
$close_datetime = getDatetimeTimestamp($cross_date_TIM, $store_time[1]); //今跨日营业的结束时间
if ($start_datetime >= $open_datetime && $end_datetime <= $close_datetime) {
return true;
}
//昨跨日结业时间
$date_TIM = strtotime('-1 day', strtotime(date('Y-m-d', $start_datetime)));
$cross_date_TIM = strtotime(date('Y-m-d', $start_datetime));
$open_datetime = getDatetimeTimestamp($date_TIM, $store_time[0]); //昨跨日营业的起始时间
$close_datetime = getDatetimeTimestamp($cross_date_TIM, $store_time[1]); //昨跨日营业的结束时间
if ($start_datetime >= $open_datetime && $end_datetime <= $close_datetime) {
return true;
}
}
return false;
}
/**
* 将日期和时间拼接成时间戳
*
* @param int $startDatetime 起始时间戳
* @param string $time 时间点字符串
* @return int 时间戳
*/
function getDatetimeTimestamp(int $startDatetime, string $time)
{
return strtotime(date('Y-m-d', $startDatetime) . " {$time}");
}