我正在编写一个预约安排系统。它会检查多个 Google 日历。
我将一天(上午 9:00 至下午 6:00)划分为 10 分钟时段。
现在我有一个数组,其中包含相应的插槽以及该插槽是否可用。
[
[ 'slot' => '2024-01-01 09:00:00', 'available' => 'no' ],
[ 'slot' => '2024-01-01 09:10:00', 'available' => 'no' ],
[ 'slot' => '2024-01-01 09:20:00', 'available' => 'no' ],
[ 'slot' => '2024-01-01 09:30:00', 'available' => 'no' ],
[ 'slot' => '2024-01-01 09:40:00', 'available' => 'no' ],
[ 'slot' => '2024-01-01 09:50:00', 'available' => 'no' ],
[ 'slot' => '2024-01-01 10:00:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 10:10:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 10:20:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 10:30:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 10:40:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 10:50:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 11:00:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 11:10:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 11:20:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 11:30:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 11:40:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 11:50:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 12:00:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 12:10:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 12:20:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 12:30:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 12:40:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 12:50:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 13:00:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 13:10:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 13:20:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 13:30:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 13:40:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 13:50:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 14:00:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 14:10:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 14:20:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 14:30:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 14:40:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 14:50:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 15:00:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 15:10:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 15:20:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 15:30:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 15:40:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 15:50:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 16:00:00', 'available' => 'no' ],
[ 'slot' => '2024-01-01 16:10:00', 'available' => 'no' ],
[ 'slot' => '2024-01-01 16:20:00', 'available' => 'no' ],
[ 'slot' => '2024-01-01 16:30:00', 'available' => 'no' ],
[ 'slot' => '2024-01-01 16:40:00', 'available' => 'no' ],
[ 'slot' => '2024-01-01 16:50:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 17:00:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 17:10:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 17:20:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 17:30:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 17:40:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 17:50:00', 'available' => 'yes' ]
]
我的可预订预约时间为30分钟长。
如何查看哪些时段可用?在这种情况下,必须始终有 3 个连续的插槽,且没有“否”。我需要这 3 个时段的开始时间,以便我可以为客户预订它们。
这个问题解决起来非常简单,基本上你只需循环 10 分钟的时段,如果有一个时段可用,并且接下来的两个时段也可用,那么该时段就可以预订。例如
$slots = [ // your data... ];
$bookableAppointments = array();
// Loop over each slot, but stop 2 slots before the end
// (the last two cannot be the start of a 30-minute segment)
for ($i = 0; $i < count($slots) - 2; $i++) {
// Check if the current slot is available ('yes')
if ($slots[$i]['available'] === 'yes') {
// Check if the next two consecutive slots are also available ('yes')
if ($slots[$i + 1]['available'] === 'yes' && $slots[$i + 2]['available'] === 'yes') {
// Found a slot with the next two consecutive slots also available
// This slot can be the start of a 30-minute bookable appointment
$bookableAppointments[] = $slots[$i]['slot'];
}
}
}
// Print the list of bookable appointments
print_r($bookableAppointments);
如果您想改变预约的长度,您可以将其指定为每个预约的时段数。
我建议这种更通用的方法,它允许每个预约的槽数可变,并且有一个轻微的优化,因为循环将“跳过”它找到的任何“否”条目,从而避免再次测试这些条目的需要:
// assumes array of slots is available at $slots
// result - list of available times
$available = [];
// configurable parameter
$slotsPerAppointment = 3;
// main loop
$startSlot = 0;
while (isset($slots[$startSlot])) {
$finishSlot = $startSlot + $slotsPerAppointment - 1;
if (!isset($slots[$finishSlot])) {
// not enough slots left in the list - we are finished
break;
}
// test each of the slots between the current $startSlot
// and $finishSlot, but test in reverse
// order for performance optimisation
$found = true;
for ($testSlot = $finishSlot; $testSlot >= $startSlot; $testSlot--) {
if ($slots[$testSlot]['available'] == 'no') {
$found = false;
// skip past the 'no' slot
$startSlot = $testSlot + 1;
break;
}
}
if ($found) {
$available[] = $slots[$startSlot]['slot'];
$startSlot++;
}
}
// show result
print_r($available);
您正在处理一个次优的参考数组。通过创建二维数据数组,您可以强制代码手动遍历并强力检查槽。相反,创建一个关联映射/查找数组以使搜索更简单、更高效。使用“已预订”等明确的术语可以避免上下文与“是”和“否”之间的任何混淆。
$vacancies = [
...
'2024-01-01 09:40:00' => 'booked',
'2024-01-01 09:50:00' => 'booked',
'2024-01-01 10:00:00' => null,
'2024-01-01 10:10:00' => null,
...
];
有 3 种可能的结果。所有时段均可用、所有时段均存在但不可用、以及至少有一个时段出现在工作时间之外。当数组中存在所有槽时,返回一个布尔值;当数组中不存在槽时,抛出异常(因为搜索到的值“越界”)。
代码:(演示)
function is30MinuteSessionVacant(array $vacancies, string $dateTime): bool
{
for ($addMinutes = 0; $addMinutes < 30; $addMinutes += 10) {
$dateTime = date('Y-m-d H:i:s', strtotime("$dateTime +{$addMinutes} minutes"));
if (!key_exists($dateTime, $vacancies)) {
throw new Exception('Proposed time is not within business hours');
}
if (isset($vacancies[$dateTime])) {
return false;
}
}
return true;
}
执行:
$newTests = [
'2024-01-01 09:50:00',
'2024-01-01 10:00:00',
'2024-01-01 15:40:00',
'2024-01-01 17:40:00',
];
foreach ($newTests as $test) {
echo "\n$test: ";
try {
echo is30MinuteSessionVacant($vacancies, $test) ? 'available' : 'unavailable';
} catch (Exception $e) {
echo $e->getMessage();
}
}
输出:
2024-01-01 09:50:00: unavailable
2024-01-01 10:00:00: available
2024-01-01 15:40:00: unavailable
2024-01-01 17:40:00: Proposed time is not within business hours
$input = [
[ 'slot' => '2024-01-01 09:00:00', 'available' => 'no' ],
[ 'slot' => '2024-01-01 09:10:00', 'available' => 'no' ],
[ 'slot' => '2024-01-01 09:20:00', 'available' => 'no' ],
[ 'slot' => '2024-01-01 09:30:00', 'available' => 'no' ],
[ 'slot' => '2024-01-01 09:40:00', 'available' => 'no' ],
[ 'slot' => '2024-01-01 09:50:00', 'available' => 'no' ],
[ 'slot' => '2024-01-01 10:00:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 10:10:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 10:20:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 10:30:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 10:40:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 10:50:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 11:00:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 11:10:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 11:20:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 11:30:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 11:40:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 11:50:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 12:00:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 12:10:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 12:20:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 12:30:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 12:40:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 12:50:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 13:00:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 13:10:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 13:20:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 13:30:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 13:40:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 13:50:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 14:00:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 14:10:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 14:20:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 14:30:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 14:40:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 14:50:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 15:00:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 15:10:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 15:20:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 15:30:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 15:40:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 15:50:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 16:00:00', 'available' => 'no' ],
[ 'slot' => '2024-01-01 16:10:00', 'available' => 'no' ],
[ 'slot' => '2024-01-01 16:20:00', 'available' => 'no' ],
[ 'slot' => '2024-01-01 16:30:00', 'available' => 'no' ],
[ 'slot' => '2024-01-01 16:40:00', 'available' => 'no' ],
[ 'slot' => '2024-01-01 16:50:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 17:00:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 17:10:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 17:20:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 17:30:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 17:40:00', 'available' => 'yes' ],
[ 'slot' => '2024-01-01 17:50:00', 'available' => 'yes' ]
];
过滤掉“可用”等于“是”的项目。然后循环遍历这些过滤后的项目,并检查接下来的两个索引是否存在(注意,
array_filter
不会重新索引它创建的数组,否则这种方法将不起作用):
$result = [];
$availables = array_filter($input, fn($item) => $item['available'] === 'yes');
foreach ($availables as $index => $available) {
if (array_key_exists($index + 1, $availables) && array_key_exists($index + 2, $availables)) {
$result[] = $available;
}
}
print_r($result);
输出(包含所有带有 'available' === 'yes' 的项目,但不包含 15:40:00 & 15:50:00 和 17:40:00 & 17:50:00 的项目):
Array
(
[0] => Array
(
[slot] => 2024-01-01 10:00:00
[available] => yes
)
[1] => Array
(
[slot] => 2024-01-01 10:10:00
[available] => yes
)
[2] => Array
(
[slot] => 2024-01-01 10:20:00
[available] => yes
)
[3] => Array
(
[slot] => 2024-01-01 10:30:00
[available] => yes
)
[4] => Array
(
[slot] => 2024-01-01 10:40:00
[available] => yes
)
[5] => Array
(
[slot] => 2024-01-01 10:50:00
[available] => yes
)
[6] => Array
(
[slot] => 2024-01-01 11:00:00
[available] => yes
)
[7] => Array
(
[slot] => 2024-01-01 11:10:00
[available] => yes
)
[8] => Array
(
[slot] => 2024-01-01 11:20:00
[available] => yes
)
[9] => Array
(
[slot] => 2024-01-01 11:30:00
[available] => yes
)
[10] => Array
(
[slot] => 2024-01-01 11:40:00
[available] => yes
)
[11] => Array
(
[slot] => 2024-01-01 11:50:00
[available] => yes
)
[12] => Array
(
[slot] => 2024-01-01 12:00:00
[available] => yes
)
[13] => Array
(
[slot] => 2024-01-01 12:10:00
[available] => yes
)
[14] => Array
(
[slot] => 2024-01-01 12:20:00
[available] => yes
)
[15] => Array
(
[slot] => 2024-01-01 12:30:00
[available] => yes
)
[16] => Array
(
[slot] => 2024-01-01 12:40:00
[available] => yes
)
[17] => Array
(
[slot] => 2024-01-01 12:50:00
[available] => yes
)
[18] => Array
(
[slot] => 2024-01-01 13:00:00
[available] => yes
)
[19] => Array
(
[slot] => 2024-01-01 13:10:00
[available] => yes
)
[20] => Array
(
[slot] => 2024-01-01 13:20:00
[available] => yes
)
[21] => Array
(
[slot] => 2024-01-01 13:30:00
[available] => yes
)
[22] => Array
(
[slot] => 2024-01-01 13:40:00
[available] => yes
)
[23] => Array
(
[slot] => 2024-01-01 13:50:00
[available] => yes
)
[24] => Array
(
[slot] => 2024-01-01 14:00:00
[available] => yes
)
[25] => Array
(
[slot] => 2024-01-01 14:10:00
[available] => yes
)
[26] => Array
(
[slot] => 2024-01-01 14:20:00
[available] => yes
)
[27] => Array
(
[slot] => 2024-01-01 14:30:00
[available] => yes
)
[28] => Array
(
[slot] => 2024-01-01 14:40:00
[available] => yes
)
[29] => Array
(
[slot] => 2024-01-01 14:50:00
[available] => yes
)
[30] => Array
(
[slot] => 2024-01-01 15:00:00
[available] => yes
)
[31] => Array
(
[slot] => 2024-01-01 15:10:00
[available] => yes
)
[32] => Array
(
[slot] => 2024-01-01 15:20:00
[available] => yes
)
[33] => Array
(
[slot] => 2024-01-01 15:30:00
[available] => yes
)
[34] => Array
(
[slot] => 2024-01-01 16:50:00
[available] => yes
)
[35] => Array
(
[slot] => 2024-01-01 17:00:00
[available] => yes
)
[36] => Array
(
[slot] => 2024-01-01 17:10:00
[available] => yes
)
[37] => Array
(
[slot] => 2024-01-01 17:20:00
[available] => yes
)
[38] => Array
(
[slot] => 2024-01-01 17:30:00
[available] => yes
)
)