使用 PHP 从带有 start_time 和 end_time 的多维数组中查找总小时数?

我正在尝试使用start_time和计算正确的总小时数end_time

这里我使用的算法是由@Pilan 提供的:

  1. 对于每组时间预订,执行以下操作

  2. 找到最小的start_time

  3. 将和duration之间添加到start_timeend_timesum

  4. 查找下一个最小的时间预订start_time

  5. IF start_time<previous_end_time减去sumEND IF的差值

  6. 在和duration之间添加start_timeend_time

  7. 跳到4,直到没有匹配的元素为止。

使用上面的内容我成功创建了以下代码:

<?php

class Helper 

{

    

     public static function minToHour($minutes)

    {

        if (empty($minutes)) {

            return 0;

        }

        $hours = floor($minutes / 60);

        $min = $minutes - ($hours * 60);


        return $hours . ":" . $min;

    }

public static function getMinsBetweenTwoTimes($start, $end)

    {

        $datetime1 = strtotime($start);

        $datetime2 = strtotime($end);

        $interval = abs($datetime2 - $datetime1);

        $minutes = round($interval / 60);

        return $minutes;

    }

   

}

$array =array (

  '2020-07-14' => 

  array (

  

    array (

      'start_time' => '09:00:00',

      'end_time' => '13:00:00',

      'hours' => '4 hours 0 mins',

    ),

    1 => 

    array (

      'start_time' => '13:30:00',

      'end_time' => '16:30:00',

      'hours' => '3 hours 0 mins',

    ),

    2 => 

    array (

      'start_time' => '09:00:00',

      'end_time' => '14:00:00',

      'hours' => '5 hours 0 mins',

    ),

  ),

  '2020-07-15' => 

  array (


    array (

      'start_time' => '13:30:00',

      'end_time' => '17:00:00',

      'hours' => '3 hours 30 mins',

    ),

    1 => 

    array (

      'start_time' => '09:00:00',

      'end_time' => '14:00:00',

      'hours' => '5 hours 0 mins',

    ),

  ),

);

一只萌萌小番薯
浏览 120回答 2
2回答

慕虎7371278

这是我对你的问题的解决方案。我不知道我是否理解正确,但基本上这是算法:1-将所有时间字符串转换为整数并对参加时间段的每个日期列表进行排序。2- 合并每个日期的重叠时段,例如,如果一个时段从 9 点到 12 点,另一个时段从 11 点到 13 点,则将其合并为从 9 点到 13 点的单个时段。3- 将每个日期的所有参加时间相加。<?php$array = [    '2020-07-14' =>[        [            'start_time' => '09:00:00',            'end_time' => '13:00:00',            'hours' => '4 hours 0 mins',        ],        [            'start_time' => '13:30:00',            'end_time' => '16:30:00',            'hours' => '3 hours 0 mins',        ],        [            'start_time' => '09:00:00',            'end_time' => '14:00:00',            'hours' => '5 hours 0 mins',        ],        [            'start_time' => '17:00:00',            'end_time' => '18:00:00',            'hours' => '1 hours 0 mins',        ]    ],    '2020-07-15' => [        [            'start_time' => '09:00:00',            'end_time' => '14:00:00',            'hours' => '5 hours 0 mins',        ],        [            'start_time' => '13:30:00',            'end_time' => '17:00:00',            'hours' => '4 hours 30 mins',        ]    ],];// Convert all times strings into integers and sort each day list// by the start time$r = parseTimesAndSort($array);// Combine overlaping periods in a single period$r = flatternOverlaps($r);// Sum all the periods in each date$r = sumPeriods($r);// Applly the result to the original arrayforeach($r as $date => $item){    $array[$date]['total_attended_hours'] = $item;}print_r($array);/** * Given a time string returns the number of seconds from 00:00:00 as integer. * example: 09:30:10 => 34210 (9*3600 + 30*60 + 10) * @param $time * @return int */function timeToSeconds($time){    $list = explode(":", $time);    return $list[0] * 3600 + $list[1] * 60 + $list[2];}/** * Given an integer as seconds returns the time string in 00:00:00 format. * example: 34210 => 09:30:10 * @param $value * @return string */function secondsToTime($value){    $hours = floor($value/3600);    $min = floor(($value%3600) / 60);    $secods = floor($value % 60);    return str_pad($hours, 2, "0", STR_PAD_LEFT)        .":".str_pad($min, 2, "0", STR_PAD_LEFT)        .":".str_pad($secods, 2, "0", STR_PAD_LEFT);}/** * Function to compare two periods * @param $a * @param $b * @return int */function sortByStartTime($a, $b){    if ($a['start_time'] == $b['start_time']){        return 0;    }    return $a['start_time'] < $b['start_time'] ? -1 : 1;}/** * Parses the periods string times to integers and sorts them * @param $array * @return array */function parseTimesAndSort($array){    $r = [];    foreach($array as $date => $list){        $current = [];        foreach($list as $item){            $current[] = [                'start_time' => timeToSeconds($item['start_time']),                'end_time' => timeToSeconds($item['end_time']),            ];        }        usort($current, 'sortByStartTime');        $r[$date] = $current;    }    return $r;}/** * Finds overlapping periods and combines them * @param $array * @return array */function flatternOverlaps($array){    $r = [];    foreach($array as $date => $list){        $currentList = [];        $prev = null;        foreach($list as $item){            if ($prev && $item['start_time'] < $prev['end_time']){                if ($item['end_time'] > $prev['end_time']) {                    $prev['end_time'] = $item['end_time'];                }            }            else{                $currentList[] = $item;            }            // Point prev to the last item in the current list            $prev = &$currentList[count($currentList)-1];        }        unset($prev);        $r[$date] = $currentList;    }    return $r;}/** * Sums the periods of each date * @param $array * @return array */function sumPeriods($array){    $r = [];    foreach($array as $date => $list){        $seconds = array_reduce($list, function($carry, $item){ return $carry + $item['end_time'] - $item['start_time']; }, 0);        $r[$date] = secondsToTime($seconds);    }    return $r;}

神不在的星期二

我更改了 2 行,81 和 82(如下所示)。您不需要 strtotime($previous_end_time) 来比较它,因为时间是 24 小时制,而且当您减去时,您想要减去 $previous_end_time 而不是 $item['end_time']。if&nbsp;(($item['start_time'])&nbsp;<&nbsp;$previous_end_time)&nbsp;{ &nbsp;&nbsp;$sum&nbsp;-=&nbsp;Helper::getMinsBetweenTwoTimes($item['start_time'],&nbsp;$previous_end_time); }
打开App,查看更多内容
随时随地看视频慕课网APP