昨天我在加总日期时间间隔时问了一个问题,并被指向该线程-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的屏幕截图(总时数粗略地圈了一下),这也显示了我的功能应加在一起的时间戳。
答案 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");