PHP获取日期数组,从一个长日期范围中分割出来

参考我的原始帖子(PHP split data range to get only chunks free),我做了一些实现,以获得更好的结果,但在某些情况下仍然不正确。


我的目标是拆分原始范围日期,以仅获得未被活动占用的空闲块。


这是我在 php 中的实际脚本:


function date_compare($a, $b)

{

    $t1 = strtotime($a['start']);

    $t2 = strtotime($b['start']);

    return $t1 - $t2;


$fullrange = array(   // <----------------------------------- one month range to split

   "start" => "2019-12-01 00:00:00",

   "end" => "2019-12-31 23:59:59"

);


$result[] = $fullrange;


$array_activities = array( // <--------------------------- activities (busy ranges)

  0 => array(

      "start" => "2019-12-08 09:00:00",

      "end" => "2019-12-08 10:00:00"


  ),

  1 => array(

      "start" => "2019-12-07 09:00:00",

      "end" => "2019-12-07 17:40:00"

  ),

  2 => array(

      "start" => "2019-12-10 10:00:00",

      "end" => "2019-12-15 17:00:00"

  ),

  3 => array(

      "start" => "2019-12-11 08:00:00",

      "end" => "2019-12-17 21:00:00"

  ),

  4 => array(

      "start" => "2019-12-08 08:57:05",

      "end" => "2019-12-08 19:00:00"

  ),

  5 => array(

      "start" => "2019-12-04 10:00:00",

      "end" => "2019-12-05 17:00:00"

  ),

    6 => array(

      "start" => "2019-12-20 10:00:00",

      "end" => "2019-12-31 23:59:59"

  ),

    7 => array(

      "start" => "2019-12-16 10:00:00",

      "end" => "2019-12-31 23:59:59"

  )


);



// reorder array of activities by date start  

usort($array_activities, 'date_compare');


foreach ( $array_activities as $index_1 => $array_activity ) {


foreach ($result as $index_2 => $r) {


    if ( $r['start'] < $array_activity['start'] && $array_activity['start'] < $r['end'] ) {


        $temp = new Datetime($array_activity['start']);

        $temp->modify("-1 second");


        $result[$index_2]['end'] = $temp->format("Y-m-d H:i:s");


        if ( $r['start'] < $array_activity['end'] && $array_activity['end'] < $r['end'] ) {


        $result[] = array("start" => $array_activity['start'], "end" => $r['end']);


        }


    }


}


翻阅古今
浏览 105回答 2
2回答

波斯汪

以下功能应该做到这一点(如果我没有错过任何东西)。对于每个活动,它会遍历所有空闲范围,检查活动是否重叠并相应地调整/创建新范围。请注意,理想情况下,您的“句点”条目应该是对象(具有start和end作为DateTime属性),以便为函数提供更强的签名/减少多余代码的数量。function getFreeTimeRanges(array $fullRange, array $activities): array{&nbsp; $freeRanges = [[&nbsp; &nbsp; 'start' => new \DateTime($fullRange['start']),&nbsp;&nbsp; &nbsp; 'end' => new \DateTime($fullRange['end'])&nbsp; ]];&nbsp; foreach ($activities as $activity) {&nbsp; &nbsp; $activityStart = new \DateTime($activity['start']);&nbsp; &nbsp; $activityEnd = new \DateTime($activity['end']);&nbsp; &nbsp; foreach ($freeRanges as &$range) {&nbsp; &nbsp; &nbsp; $activityIsOverlapping = $activityStart < $range['end']&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; && $activityEnd > $range['start'];&nbsp; &nbsp; &nbsp; if ($activityIsOverlapping) {&nbsp; &nbsp; &nbsp; &nbsp; $activityStartsLater = $activityStart > $range['start'];&nbsp; &nbsp; &nbsp; &nbsp; $activityEndsBefore = $activityEnd < $range['end'];&nbsp; &nbsp; &nbsp; &nbsp; if ($activityStartsLater) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ($activityEndsBefore) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $freeRanges[] = [&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'start' => $activityEnd->modify('+1 second'),&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'end' => $range['end']&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $range['end'] = $activityStart->modify('-1 second');&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; elseif ($activityEndsBefore) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $range['start'] = $activityEnd->modify('+1 second');&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; }&nbsp; uasort($freeRanges, static function (array $range1, array $range2) {&nbsp; &nbsp; return $range1['start'] <=> $range2['start'];&nbsp; });&nbsp; return array_map(static function ($range) {&nbsp; &nbsp; return [&nbsp; &nbsp; &nbsp; 'start' => $range['start']->format('Y-m-d H:i:s'),&nbsp;&nbsp; &nbsp; &nbsp; 'end' => $range['end']->format('Y-m-d H:i:s')&nbsp; &nbsp; ];&nbsp; }, $freeRanges);}$fullRange = ['start' => '2019-12-01 00:00:00', 'end' => '2019-12-31 23:59:59'];$activities = [&nbsp; 0 => ['start' => '2019-12-08 09:00:00', 'end' => '2019-12-08 10:00:00'],&nbsp; 1 => ['start' => '2019-12-07 09:00:00', 'end' => '2019-12-07 17:40:00'],&nbsp; 2 => ['start' => '2019-12-10 10:00:00', 'end' => '2019-12-15 17:00:00'],&nbsp; 3 => ['start' => '2019-12-11 08:00:00', 'end' => '2019-12-17 21:00:00'],&nbsp; 4 => ['start' => '2019-12-08 08:57:05', 'end' => '2019-12-08 19:00:00'],&nbsp; 5 => ['start' => '2019-12-04 10:00:00', 'end' => '2019-12-05 17:00:00'],&nbsp; 6 => ['start' => '2019-12-20 10:00:00', 'end' => '2019-12-31 23:59:59'],&nbsp; 7 => ['start' => '2019-12-16 10:00:00', 'end' => '2019-12-31 23:59:59']];print_r(getFreeTimeRanges($fullRange, $activities));演示:https ://3v4l.org/p8Kvl

明月笑刀无情

这可能适用于所有情况:foreach ( $array_activities as $index_1 => $array_activity ) {&nbsp; &nbsp; foreach ($result as $index_2 => $r) {&nbsp; &nbsp; &nbsp; &nbsp; if ( $r['start'] < $array_activity['start'] && $array_activity['start'] < $r['end'] ) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $temp = new Datetime($array_activity['start']);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $temp->modify("-1 second");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $result[$index_2]['end'] = $temp->format("Y-m-d H:i:s");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ( $r['start'] < $array_activity['end'] && $array_activity['end'] < $r['end'] ) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $result[] = array("start" => $array_activity['start'], "end" => $r['end']);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ( $array_activity['start'] <= $r['start'] && $array_activity['end'] >= $r['end'] ) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; unset($result[$index_2]);&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; foreach ($result as $index_2 => $r) {&nbsp; &nbsp; &nbsp; &nbsp; if ( $r['start'] < $array_activity['end'] && $array_activity['end'] < $r['end'] ) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $temp = new Datetime($array_activity['end']);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $temp->modify("+1 second");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $result[$index_2]['start'] = $temp->format("Y-m-d H:i:s");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $result[$index_2]['end'] = $r['end'];&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; echo '<pre>';var_dump($result);echo '</pre>';}
打开App,查看更多内容
随时随地看视频慕课网APP