You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多维数组与foreach循环下,取首尾索引计算员工项目每日工时

解决方案:按项目维度计算员工每日工作时长

嘿,看起来你已经把员工任务分配功能的大部分开发搞定了,现在就差按项目维度计算每日工时这一步了。我刚好有个贴合你需求的PHP实现方案,完全利用多维数组的首尾索引来判断项目的首日、末日和中间工作日,严格遵循你给定的计算规则:

核心思路

  1. 先定义办公时间常量,转成时间戳方便计算时长差值
  2. 逐层遍历你的三维数组(员工ID→项目ID→日期)
  3. 对每个项目,获取日期列表的首尾索引,以此区分首日、末日、中间工作日
  4. 针对不同场景计算工时,最后替换原数组中的起止时间为计算结果

PHP代码实现

<?php
// 设置时区(根据业务需求调整,比如国内用Asia/Shanghai)
date_default_timezone_set('Asia/Shanghai');

// 定义办公时间常量,转换为时间戳简化计算
define('WORK_START', strtotime('09:30:00'));
define('WORK_END', strtotime('19:30:00'));
define('STANDARD_DAILY_HOURS', 10); // 每日标准工时

// 模拟你的现有三维数组结构(员工ID→项目ID→日期→起止时间)
$employeeTaskData = [
    'emp_001' => [
        'proj_001' => [
            '2024-05-20' => ['t_start_time' => '2024-05-20 10:15:00', 't_end_time' => '2024-05-20 19:30:00'],
            '2024-05-21' => ['t_start_time' => '2024-05-21 09:30:00', 't_end_time' => '2024-05-21 19:30:00'],
            '2024-05-22' => ['t_start_time' => '2024-05-22 09:30:00', 't_end_time' => '2024-05-22 15:45:00']
        ],
        'proj_002' => [
            '2024-05-23' => ['t_start_time' => '2024-05-23 13:30:00', 't_end_time' => '2024-05-23 19:30:00']
        ]
    ],
    'emp_002' => [
        'proj_003' => [
            '2024-05-20' => ['t_start_time' => '2024-05-20 09:30:00', 't_end_time' => '2024-05-20 19:30:00'],
            '2024-05-21' => ['t_start_time' => '2024-05-21 09:30:00', 't_end_time' => '2024-05-21 19:30:00'],
            '2024-05-22' => ['t_start_time' => '2024-05-22 09:30:00', 't_end_time' => '2024-05-22 12:10:00']
        ]
    ]
];

// 处理数组,计算并替换每日工时
foreach ($employeeTaskData as $empId => &$projects) {
    foreach ($projects as $projId => &$dateTasks) {
        // 获取当前项目的所有日期索引,用于判断首日和末日
        $dateKeys = array_keys($dateTasks);
        $firstDate = reset($dateKeys);
        $lastDate = end($dateKeys);

        foreach ($dateTasks as $date => &$task) {
            $startTs = strtotime($task['t_start_time']);
            $endTs = strtotime($task['t_end_time']);

            $dailyHours = 0;
            if ($date === $firstDate && $date === $lastDate) {
                // 场景1:项目仅持续1天,取办公时间内的有效时长
                $effectiveStart = max($startTs, WORK_START);
                $effectiveEnd = min($endTs, WORK_END);
                $dailyHours = round(($effectiveEnd - $effectiveStart) / 3600, 2);
            } elseif ($date === $firstDate) {
                // 场景2:项目首日,计算任务开始到下班的时长
                $effectiveStart = max($startTs, WORK_START);
                $dailyHours = round((WORK_END - $effectiveStart) / 3600, 2);
            } elseif ($date === $lastDate) {
                // 场景3:项目末日,计算上班到任务结束的时长
                $effectiveEnd = min($endTs, WORK_END);
                $dailyHours = round(($effectiveEnd - WORK_START) / 3600, 2);
            } else {
                // 场景4:中间工作日,直接按标准10小时计算
                $dailyHours = STANDARD_DAILY_HOURS;
            }

            // 替换原起止时间为每日工时(可根据需求调整结构,比如保留原字段+新增工时)
            $task = ['daily_hours' => $dailyHours];
        }
    }
}

// 打印结果(实际业务中可按需存储或返回)
echo "<pre>";
print_r($employeeTaskData);
echo "</pre>";
?>

关键细节说明

  • 时区处理:开头设置了时区,避免因服务器时区差异导致时间计算错误
  • 边界值处理:比如首日任务开始时间早于上班时间时,自动从上班时间开始计算;末日任务结束时间晚于下班时间时,自动截止到下班时间
  • 精度控制:工时保留两位小数,更符合实际办公场景的统计需求
  • 灵活调整:如果需要保留原起止时间字段,只需修改最后替换的逻辑,比如改成$task['daily_hours'] = $dailyHours;即可

额外建议

如果需要处理非工作日(比如周末),可以添加判断:用date('N', strtotime($date))获取日期对应的星期数(1=周一,5=周五),非工作日的工时可设为0或跳过计算。

内容的提问来源于stack exchange,提问作者Mithun M

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:53:50