【问题标题】:How to get total hours from start time and end time with multi dimensional array along with over lapping check?如何使用多维数组以及重叠检查从开始时间和结束时间获得总小时数?
【发布时间】:2020-11-12 09:53:59
【问题描述】:

我有以下情况,我需要仅在特定日期数组中检查 重叠 并获取总参加时间。

array (
  '2020-07-14' => 
  array (
    'total_attended_hours' => 0,
    0 => 
    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 (
    'total_attended_hours' => 0,
    0 => 
    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',
    ),
  ),
)

在上面的例子中,日期为2020-07-14,我们有start_time and end_time:- total_attended_hoursshould be equals to7 小时 30 分钟

对于下一个2020-07-15,它应该是total_attended_hours = 8 hours 0 mins

Playground

以下数组的新问题


$data = [
  '2020-07-14' => 
  [
    [
      'start_time' => '14:15:00',
      'end_time' => '17:45:00',
    ],[
      'start_time' => '14:30:00',
      'end_time' => '17:30:00',
    ],[
      'start_time' => '14:30:00',
      'end_time' => '17:30:00',
    ],
  ],
  '2020-07-15' => [
    [
      'start_time' => '13:30:00',
      'end_time' => '17:00:00',
    ],[
      'start_time' => '09:00:00',
      'end_time' => '14:00:00',
    ],
  ],
];

结果:-

Array
(
    [2020-07-14] => Array
        (
            [0] => Array
                (
                    [start_time] => 14:15:00
                    [end_time] => 17:45:00
                )

            [1] => Array
                (
                    [start_time] => 14:30:00
                    [end_time] => 17:30:00
                )

            [2] => Array
                (
                    [start_time] => 14:30:00
                    [end_time] => 17:30:00
                )

            [total_attended_hours] => 03:15:00
        )

[total_attended_hours] => 03:15:00 应该是 [total_attended_hours] => 03:30:00

【问题讨论】:

  • 您能通过var_export 提供您的阵列吗?
  • 您至少应该向我们展示您在 php 中的尝试,以便我们为您提供帮助
  • @Pilan 我已经用 var_export 更新了问题

标签: php arrays datetime time


【解决方案1】:

这里有算法:

  1. 对于每组时间预订,请执行以下操作
  2. 找到最小的start_time
  3. start_timeend_time 之间的duration 添加到sum
  4. 通过start_time查找下一个最小的时间预订
  5. IF current_end_time previous_end_time 跳转到4 END IF
  6. IF start_time previous_end_time 从sum END IF 中减去差异
  7. start_timeend_time 之间添加duration
  8. 跳到 4 直到没有匹配的元素。

编码愉快:)

编辑 - 添加更干净的实现

function getSortedDays(array $days): array {
    return array_map(function (array $day) {
       array_multisort(array_column($day, 'start_time'), SORT_ASC, $day);
       
       return $day;
    }, $days);
}

function addTotalAttendedHours(array $days): array {
    $sortedDays = getSortedDays($days);
    
    $days = array_map(function (array $day) {
        $sum = (new DateTime())->setTimestamp(0);
        $previousEnd = null;
        
        foreach ($day as $time) {
            $currentStart = new DateTimeImmutable($time['start_time']);
            $currentEnd = new DateTimeImmutable($time['end_time']);

            if ($currentEnd < $previousEnd) continue; // this has been added
            
            $sum->add($currentStart->diff($currentEnd));
            
            if ($previousEnd !== null && $currentStart < $previousEnd) {
                $sum->sub($currentStart->diff($previousEnd));
            }
            
            $previousEnd = $currentEnd;
        }
        
        $attendedSeconds = $sum->getTimestamp();
        $day['total_attended_hours'] = sprintf(
            '%02u:%02u:%02u',
            $attendedSeconds / 60 / 60,
            ($attendedSeconds / 60) % 60,
            $attendedSeconds % 60
        );
        
        return $day;
    }, $sortedDays);
    
    return $days;
}

工作example

【讨论】:

  • 我试过你的算法,它给出了这个结果。 Playground link
  • $sum -= Helper::getMinsBetweenTwoTimes($item['start_time'], $item['end_time']); 你需要 start_timeprevious_end_time 之间的区别 - 做得很好,先生 :)
  • 非常感谢您,如果没有您的算法,这将是不可能的。你们是 COVID-19 中的真正战士。我在家里工作,在这里我们没有比你们更高级的帮助。万分感激。再次感谢
  • @Php 我添加了一个更干净的实现来帮助您编写未来的代码
  • 我正要对日期进行排序,你添加了这个很棒的解决方案,非常感谢队友
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-05
  • 1970-01-01
  • 1970-01-01
  • 2013-08-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多