使用foreach循环添加DateTime时间间隔

时间:2019-06-06 07:47:18

标签: php mysql mysqli

昨天我在加总日期时间间隔时问了一个问题,并被指向该线程-How we can add two date intervals in PHP

这很棒,并且很有意义,但是当我尝试执行提交的答案在foreach循环中说的即时消息时,结果最终是不正确的。

这是我制作的一个功能,它可以获取工作人员的进出时间,它们存储在数据库中,并使用php的date(H:i:s)创建。

我的功能可以获取任何给定员工的所有进出时间,而我正在使用的报表功能需要显示他们工作的总时数。

我试图通过将时间转换为datetime对象并使用-> diff来获取时间间隔并由此计算该天的小时数来实现这一点,然后尝试使用foreach循环将这些时间间隔相加,从而得出总计在给定日期范围内工作的小时数。

整个功能是这样的:

function getTotalHours($staff_id,$from_date,$to_date){

    $sql = "SELECT * FROM oc_staff_times WHERE date BETWEEN '$from_date' AND '$to_date' AND staff_id = '$staff_id'";
    $result = $this->conn->query($sql);

    if ($result->num_rows > 0) {
        while ($row = mysqli_fetch_assoc($result)) {
            $data[] = $row;
        }

        $base_time = new DateTime('00:00');
        $total = new DateTime('00:00');

        foreach ($data as $time) {
            $in = new DateTime($time['clock_in_time']); 
            $out = new DateTime($time['clock_out_time']); 
            $interval = $in->diff($out);
            $base_time->add($interval); 
        }

        return $total->diff($base_time)->format("%H:%I");       
    }
}

我希望获得每月总计,但是好像最终结果只有一天?这是UI的屏幕截图(总时数粗略地圈了一下),这也显示了我的功能应加在一起的时间戳。

1

2 个答案:

答案 0 :(得分:1)

您可以在单个查询中执行此操作。使用TIMEDIFF()来获取每一行的差异,然后使用TIME_TO_SEC()将其转换为秒,使用SUM()将其转换为秒,然后使用SEC_TO_TIME()将其放回时间格式-全部在MySQL中!

SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(TIMEDIFF(`clock_out_time`, `clock_in_time`))))
FROM `oc_staff_times`
WHERE `staff_id` = ?
  AND `date` BETWEEN ? AND ?

通过准备好的语句使函数起作用。

function getTotalHours($staff_id, $from_date, $to_date){
    $sql = "SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(TIMEDIFF(`clock_out_time`, `clock_in_time`))))
            FROM `oc_staff_times`
            WHERE `staff_id` = ?
              AND `date` BETWEEN ? AND ?";

    $stmt = $this->conn->prepare($sql);
    $stmt->bind_param("sss", $staff_id, $from_date, $to_date);
    $stmt->execute();
    $stmt->bind_result($totalTime);
    $stmt->fetch();
    $stmt->close();
    return $totalTime;   
}

答案 1 :(得分:1)

Qirel的答案提供了一种在SQL中执行此操作的好方法,但是,如果您想了解为什么您的代码不起作用:

$base_time = new DateTime('00:00');不会创建间隔,而是一个日期。这意味着,如果您将其添加24小时并仅询问时间部分,它将显示为“ 00:00”,因为您将在第二天结束。

一种解决方案是将$base_time声明为一个间隔,例如: $base_time = new DateInterval('PT0S');

最后直接这样输出: $base_time->format("%H:%I");