数组时间段:通过搜索的日期时间和接下来的 2 个日期时间检查预约可用性

问题描述 投票:0回答:4

我正在编写一个预约安排系统。它会检查多个 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 个时段的开始时间,以便我可以为客户预订它们。

php arrays mapping filtering
4个回答
0
投票

这个问题解决起来非常简单,基本上你只需循环 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);

0
投票

如果您想改变预约的长度,您可以将其指定为每个预约的时段数。

我建议这种更通用的方法,它允许每个预约的槽数可变,并且有一个轻微的优化,因为循环将“跳过”它找到的任何“否”条目,从而避免再次测试这些条目的需要:

// 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);

0
投票

您正在处理一个次优的参考数组。通过创建二维数据数组,您可以强制代码手动遍历并强力检查槽。相反,创建一个关联映射/查找数组以使搜索更简单、更高效。使用“已预订”等明确的术语可以避免上下文与“是”和“否”之间的任何混淆。

$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

-1
投票
$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
        )

)
© www.soinside.com 2019 - 2024. All rights reserved.