PHP计算存在重叠时间段的会议实际出勤时长(分钟)
解决重叠会议出勤时长计算问题
核心思路
先合并所有重叠或相邻的会议时段,再计算合并后各时段的总时长,就能得到实际出勤分钟数。
实现步骤
- 转换时间格式:把每个时段的
startmeeting和endmeeting转换为Unix时间戳,方便后续比较和计算。 - 排序时段:按会议开始时间对数组升序排序,确保可以按顺序处理时段。
- 合并重叠时段:遍历排序后的数组,维护一个合并后的时段列表,每次检查当前时段是否和列表最后一个时段重叠,重叠则合并,不重叠则直接加入列表。
- 计算总时长:遍历合并后的时段,计算每个时段的时长(结束时间-开始时间),转换为分钟后求和。
PHP代码实现
<?php $attendance = [ ["startmeeting"=>"2023-06-21 11:44:27", "endmeeting"=>"2023-06-21 11:50:01"], ["startmeeting"=>"2023-06-21 12:01:10", "endmeeting"=>"2023-06-21 12:15:20"], ["startmeeting"=>"2023-06-21 12:04:10", "endmeeting"=>"2023-06-21 12:17:21"], ["startmeeting"=>"2023-06-21 12:20:02", "endmeeting"=>"2023-06-21 12:30:08"], ["startmeeting"=>"2023-06-21 12:25:07", "endmeeting"=>"2023-06-21 12:31:02"], ]; // 转换为时间戳并整理数组 $timeSlots = array_map(function($item) { return [ 'start' => strtotime($item['startmeeting']), 'end' => strtotime($item['endmeeting']) ]; }, $attendance); // 按开始时间排序 usort($timeSlots, function($a, $b) { return $a['start'] - $b['start']; }); // 合并重叠时段 $merged = []; foreach ($timeSlots as $slot) { if (empty($merged)) { $merged[] = $slot; continue; } $last = &$merged[count($merged)-1]; // 当前时段与最后一个合并时段重叠,更新结束时间 if ($slot['start'] <= $last['end']) { $last['end'] = max($last['end'], $slot['end']); } else { $merged[] = $slot; } } // 计算总出勤时长(分钟) $totalMinutes = 0; foreach ($merged as $slot) { $totalMinutes += ($slot['end'] - $slot['start']) / 60; } // 输出结果,保留两位小数 echo "实际出勤时长:" . number_format($totalMinutes, 2) . " 分钟"; ?>
代码说明
strtotime():将字符串格式的时间转为Unix时间戳(单位:秒),简化时间对比操作。usort():自定义排序规则,保证时段按开始时间先后顺序排列,是合并重叠时段的前提。- 合并逻辑:通过对比当前时段的开始时间和已合并时段的最后一个结束时间,判断是否重叠,重叠则更新结束时间为两者的最大值,避免重复计算时长。
- 时长计算:将每个合并后时段的秒数差除以60得到分钟数,累加后得到总出勤时长。
内容的提问来源于stack exchange,提问作者Pedro Krns
相关产品推荐
相关产品推荐

