此脚本会检查某个时间范围内是否有 60 分钟的空档,同时考虑到已预订的空档。它适用于第一个已预订的时段,但不考虑第二个时段。另外,如果我将第一个预订时段更改为 12:10,它也不会检测到它。
基本上,想法是在范围和已预订的时段之间是否有 60 分钟的时段来显示它。
例如,如果我们有一个范围9:00to15:00并且我们有两个预订的时段从11:10和14:00,返回可用时段9:00, 10:00 and 12:10
$start_time = '2022-10-21 09:00:00'; //start time as string
$end_time = '2022-10-21 15:00:00'; //end time as string
$booked = ['2022-10-21 12:00:00','2022-10-21 13:00:00']; //booked slots as arrays
$start = DateTime::createFromFormat('Y-m-d H:i:s',$start_time); //create date time objects
$end = DateTime::createFromFormat('Y-m-d H:i:s',$end_time); //create date time objects
$time1 = $start;
$count = 0; //number of slots
$out = array(); //array of slots
for($i = $start; $i<$end;) //for loop
{
$avoid = false;
$t1 = date_timestamp_get($i);
$t2 = $t1+(60*60);
for($k=0;$k<sizeof($booked);$k+=2) //if booked hour
{
$st = DateTime::createFromFormat('Y-m-d H:i:s',$booked[$k]);
$en = DateTime::createFromFormat('Y-m-d H:i:s',$booked[$k+1]);
if( $t1 >= date_timestamp_get($st) && $t2 <= date_timestamp_get($en) )
$avoid = true; //yes. booked
}
$slots =[ $i->format('H:i'),$i->modify("+60 minutes")->format('H:i')];
if(!$avoid && $i<$end) //if not booked and less than end time
{
$count++;
array_push($out,$slots); //add slot to array
}
}
var_dump($out); //array out
Run Code Online (Sandbox Code Playgroud)
这是沙箱的链接 https://onlinephp.io/c/b0b77
附加信息
假设我们有一个从 开始的空闲时间范围10:00 until 13:00。脚本应返回的是10:00, 11:00, 以及12:00如果时间段是 则作为可能性60 min。
如果时隙是45 min. 例如,它应该返回10:00、10:45、11:30和12:15。
因此,可能的变体应该从第一个可能的选项开始,随着时隙的增加而增加 ( 45, 60, or whatever time slot is set)
该插槽不能从10:12, 10:44, or another custom time
解决方案
下面的两个解决方案均按Salman A预期Jim工作。只需使用一点不同的方法即可。
重叠预订- 提供更新
如果您按照Salman A我们的建议有重叠的预订,则必须首先将它们合并,然后仅发送唯一的间隔。我用那个函数做到了
function mergeBookings($ranges)
{
$retVal = [];
//sort date ranges by begin time
usort($ranges, function ($a, $b) {
return strcmp($a['start'], $b['start']);
});
$currentRange = [];
foreach ($ranges as $range) {
// bypass invalid value
if ($range['start'] >= $range['end']) {
continue;
}
//fill in the first element
if (empty($currentRange)) {
$currentRange = $range;
continue;
}
if ($currentRange['end'] < $range['start']) {
$retVal[] = $currentRange;
$currentRange = $range;
} elseif ($currentRange['end'] < $range['end']) {
$currentRange ['end'] = $range['end'];
}
}
if ($currentRange) {
$retVal[] = $currentRange;
}
return $retVal;
}
Run Code Online (Sandbox Code Playgroud)
然后只需在将 $booked 数组发送到脚本之前使用该函数即可。像这样
$booked = mergeBookings($booked);
Run Code Online (Sandbox Code Playgroud)
如果预订日期已排序,则可以通过简单的嵌套循环来完成此操作。注意数据中的模式;一行的结束日期和下一行的开始日期形成一个可用范围,您可以在其中创建槽:
$start_time = '2022-10-21 09:00:00';
$booked = array(
array('start' => '2022-10-21 11:10:00', 'end' => '2022-10-21 12:10:00'),
array('start' => '2022-10-21 14:00:00', 'end' => '2022-10-21 15:00:00')
);
$end_time = '2022-10-21 15:00:00';
$slot_size = 60;
// data must be sorted by date
usort($booked, function($a, $b) {
return DateTime::createFromFormat('Y-m-d H:i:s', $a['start']) <=> DateTime::createFromFormat('Y-m-d H:i:s', $b['start']);
});
$interval = new DateInterval('PT' . $slot_size . 'M');
$result = array();
for ($i = 0, $j = count($booked); $i <= $j; $i++) {
// loop count + 1 times
// first and last iterations are special
$range_start = $i === 0 ? DateTime::createFromFormat('Y-m-d H:i:s', $start_time) : DateTime::createFromFormat('Y-m-d H:i:s', $booked[$i - 1]['end']);
$range_end = $i < $j ? DateTime::createFromFormat('Y-m-d H:i:s', $booked[$i]['start']) : DateTime::createFromFormat('Y-m-d H:i:s', $end_time);
$t1 = (clone $range_start);
$t2 = (clone $range_start)->add($interval);
while ($t2 <= $range_end) {
$result[] = array('start' => $t1->format('Y-m-d H:i:s'), 'end' => $t2->format('Y-m-d H:i:s'));
$t1->add($interval);
$t2->add($interval);
}
}
var_dump($result);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
397 次 |
| 最近记录: |