【问题标题】:Adding DateTime intervals with foreach loop使用 foreach 循环添加 DateTime 间隔
【发布时间】:2019-06-06 07:47:18
【问题描述】:

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

这很棒而且很有意义。但是,当我尝试在 foreach 循环中执行提交的答案时,我得到的结果不正确。

这是我制作的一个函数,它可以获取所有员工的上班时间和下班时间,它们存储在数据库中并使用 PHP 的日期(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 的屏幕截图(总小时数被粗略圈起来)这也显示了我的函数应该添加在一起的时间戳。

【问题讨论】:

  • 不知道你要达到什么目的,但显然while()foreach() 不是同时需要的,你只能使用while():- 3v4l.org/RfTmY

标签: php mysql mysqli


【解决方案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;   
}

【讨论】:

  • 我只希望我能投票两次!感谢您的帮助,我知道您可以在查询本身中执行此操作!
  • 很高兴能够提供帮助!大多数事情都可以直接在查询中完成 - 如果可以的话,通常(但不总是)在查询时这样做更好:-)
【解决方案2】:

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-01
    • 2019-05-28
    • 1970-01-01
    • 1970-01-01
    • 2022-01-11
    • 2019-05-02
    • 1970-01-01
    • 2013-09-04
    相关资源
    最近更新 更多