用PHP计算可用时隙

用PHP计算可用时隙,php,Php,假设我有以下数据: $businessHours = [ ['09:00:00', '13:00:00'], ['14:00:00', '18:00:00'] // notice the 1 hour break ]; $appointments = [ ['10:00:00', '10:30:00'], // format is [from, until] ['15:30:00', '16:15:00']

假设我有以下数据:

    $businessHours = [
        ['09:00:00', '13:00:00'],
        ['14:00:00', '18:00:00'] // notice the 1 hour break
    ];

    $appointments = [
        ['10:00:00', '10:30:00'], // format is [from, until]
        ['15:30:00', '16:15:00']
    ];
在工作时间内,在工作休息时间外,如何收集可用的15分钟时间段

在上述情况下,结果应为:

[
    ['09:00:00', '09:15:00'],
    ['09:15:00', '09:30:00'],
    ['09:30:00', '09:45:00'],
    ['09:45:00', '10:00:00'],
                               // 10:00:00 to 10:30:00 excluded (unavailable)
    ['10:30:00', '10:45:00'],
    ['10:45:00', '11:00:00'],

    ['11:00:00', '11:15:00'],
    ['11:15:00', '11:30:00'],
    ['11:30:00', '11:45:00'],
    ['11:45:00', '12:00:00'],

    ['12:00:00', '12:15:00'],
    ['12:15:00', '12:30:00'],
    ['12:30:00', '12:45:00'],
    ['12:45:00', '13:00:00'],
                                // excluded work break
    ['14:00:00', '14:15:00'],
    ['14:15:00', '14:30:00'],
    ['14:30:00', '14:45:00'],
    ['14:45:00', '15:00:00'],

    ['15:00:00', '15:15:00'],
    ['15:15:00', '15:30:00'],
                               // 15:30:00 to 16:15:00 excluded (unavailable)
    ['16:15:00', '16:30:00'],
    ['16:30:00', '16:45:00'],
    ['16:45:00', '17:00:00'],

    ['17:00:00', '17:15:00'],
    ['17:15:00', '17:30:00'],
    ['17:30:00', '17:45:00'],
    ['17:45:00', '18:00:00'],
    
];

我提出的解决您的问题的方法是将您的工作时间和约会阵列转换为单个可用性阵列,该阵列将包含您可用的时间段

有了这个数组,我可以通过计算一段时间内可用的插槽数轻松生成所需的插槽数组,这要归功于提供的插槽持续时间(在您的示例中为15分钟)

更清楚地说,在您的示例中,您有以下几点:

$businessHours=[
['09:00:00', '13:00:00'],
['14:00:00', '18:00:00']
];
$约会=[
['10:00:00', '10:30:00'],
['15:30:00', '16:15:00']
];
但我希望使用可用性,因此我需要将
$businessHours
$appointment
转换为
$availability
数组,在本例中,该数组应为以下内容:

$availability=[
['09:00:00', '10:00:00'],
['10:30:00', '13:00:00'],
['14:00:00', '15:30:00'],
['16:15:00', '18:00:00']
];
实施 我将使用这个示例实现。我将对该功能进行一个原始实现,然后将其重构为一个合适的类

休息 我首先需要的是一系列的休息。休息是指你不在的一段时间。例如,13:00到14:00之间是因为工作时间暂停,10:00到10:30之间是因为约会

因此,简单地说,中断是每个
$businessHours
条目的最后一项和下一个条目的第一项以及每个
$appointment
条目的映射

因此,我需要创建一个返回这种映射的函数。以下是该函数:

函数数组\u结束\u到下一个\u开始($array){
$result=[];
$first=null;
$last=null;
对于($i=0;$i
这不是一个好代码,但它完成了工作(稍后我将进行重构)。此函数循环给定数组,获取该数组的最后一个值和下一个数组的第一个值,然后将它们添加到另一个数组中

此外,它还跟踪第一个元素和最后一个元素

$businessHours
上使用此函数,我得到以下数组:

[
['13:00:00', '14:00:00']
]
这正是我想要的。结合
$appointment
,我现在有了所有的休息时间:

[
['13:00:00', '14:00:00'],
['10:00:00', '10:30:00'],
['15:30:00', '16:15:00']
]
你可以注意到它们是如何不整齐的。为了解决这个问题,我使用按每个数组中的第一个小时进行排序:

usort($breaks,fn($a,$b)=>a[0]$b[0]);
注意:如果您不知道,
是最重要的

获得可用性 现在我们有了休息时间,我们可以使用在
$businessHours
上使用的相同模式来获取您的可用性

由于您在非休息时间可以使用,因此我只需重新使用
$breaks
上的
数组\u end\u to\u next\u start
功能,即可获得您不在暂停或约会期间的映射

之前,我在
$businessHours
上使用了它,如下所示:

[$breaks,$startOfDay,$endOfDay]=数组结束到下一个开始($businessHours);
现在,我将在
$breaks
上使用它,如下所示:

[$availability,$first,$last]=数组结束到下一个开始($breaks);
多亏了这两个电话,我才有了一个完整的
$availability
阵列:

$availability=[
[$startOfDay$first],
…$可用性,
[$last$endOfDay]
];
从时段生成可用性插槽 现在我们有了我们需要的,我们需要考虑最初的问题:您需要获得一个插槽阵列。早些时候,我解释说,由于插槽持续时间(在本例中为15分钟),您可以生成它

为此,我将创建一个
generate\u slot\u array\u from\u period
函数:

函数从\u期间($start,$end)生成\u插槽\u数组{
$slotDuration=15;
$start=Carbon::createFromTimeString($start);
$end=Carbon::createFromTimeString($end);
$slotCount=(int)($start->diffInMinutes($end)/$slotDuration);
$slots=[];
对于($i=0;$i<$slotCount;$i++){
$slots[]=[
$start->format('H:i:s'),
$start->addMinutes($slotDuration)->格式('H:i:s')
];
}
返回$slots;
}
有趣的是,我是如何通过得到结束时间和开始时间之间的差值(以分钟为单位)并除以时段的持续时间来了解给定开始时间的时段数的

例如,如果您从14:00:00到16:00:00有空,则两者之间的分钟差将为120。除以15,我们知道您有8个15分钟可用的插槽

接下来,我们循环8次,将这些句点添加到数组中

从可用性获取插槽 我们需要做的最后一件事是为每个可用性周期调用
generate\u slot\u array\u from\u period
。这很简单:

函数从可用性数组生成插槽数组($availability){
$slots=[];
foreach($可用性为[$start,$end]){
$slots=array\u merge(
$slots,
从生成\u插槽\u阵列\u