【问题标题】:how to sum hour/minutes from foreach如何从 foreach 总结小时/分钟
【发布时间】:2021-06-06 21:56:58
【问题描述】:

我如何总结时间以返回小时/分钟。 我需要将 IN 与 OUT 相加。 因为人们可以多次来并开始。

表格数据

|     Day    |   Hour   | Status |
|------------|----------|--------|
| 03/04/2021 | 19:45:05 | in     |
| 03/04/2021 | 20:03:50 | out    |
| 03/04/2021 | 20:04:34 | in     |
| 03/04/2021 | 20:04:51 | out    |
| 03/04/2021 | 21:04:59 | in     |
| 03/04/2021 | 23:59:59 | out    |
| 03/04/2021 | 22:08:07 | in     |
| 03/04/2021 | 22:08:55 | out    |
| 03/05/2021 | 14:46:32 | in     |
| 03/05/2021 | 19:25:09 | out    |

代码

foreach ($timesheets as $timesheet) {
    $total -= strtotime($timesheet['hour']);
}
    
// Absolute value of time difference in seconds
$diff  = abs($total);
    
// Convert $diff to minutes
$tmins = $diff / 60;
    
// Get hours
$hours = floor($tmins / 60);
    
// Get minutes
$mins = $tmins%60;

return "<b>$hours</b> hours and<b>$mins</b> minutes</b>";

数据数组

Array ( 
    [0] => Array ( [0] => 2021-03-05 [1] => 19:25:09 [2] => out )
    [1] => Array ( [0] => 2021-03-05 [1] => 14:46:32 [2] => in )
    [2] => Array ( [0] => 2021-03-04 [1] => 22:08:55 [2] => out ) 
    [3] => Array ( [0] => 2021-03-04 [1] => 22:08:07 [2] => in ) 
    [4] => Array ( [0] => 2021-03-04 [1] => 23:59:59 [2] => out ) 
    [5] => Array ( [0] => 2021-03-04 [1] => 21:04:59 [2] => in ) 
    [6] => Array ( [0] => 2021-03-04 [1] => 20:04:51 [2] => out )
    [7] => Array ( [0] => 2021-03-04 [1] => 20:04:34 [2] => in )
    [8] => Array ( [0] => 2021-03-04 [1] => 20:03:50 [2] => out ) 
    [9] => Array ( [0] => 2021-03-04 [1] => 19:42:05 [2] => in )
)

【问题讨论】:

  • 请以文字形式发布数据,而不是图片。
  • 当您避免发布可以提供文本的图像时,搜索引擎和残障人士将更容易阅读您的问题。请edit.
  • 排序乱序是否有原因?例如:in - 21:04:59in - 22:08:07,最接近的是 out - 22:08:55。是否有 ID 或其他列保留了可以对其进行分组的序列的顺序?
  • 按id order desc排序

标签: php date time mariadb


【解决方案1】:

由于strtotime 转换为 unix-timestamp 值,因此您需要提供完整的日期和时间才能获得准确的时间戳记。但是,可以使用 SQL 代替您执行此操作 - 通过使用数据透视表和一些内置的 DATETIME 函数。

数据透视表查询

首先,日期需要按日期和时间in 适当排序,其对应的日期和时间out 按您评论中所述的ID 列排序。

然后使用STR_TO_DATE(CONCAT(t.Day, ' ', t.Hour), '%Y-%m-%d %H:%i:%s') as Date_Time 将各个DATETIME 列转换为DATETIME 值。

这将创建一个数据透视表,其中每行包含单独的 inout 日期时间值。允许使用TIMESTAMPDIFF(SECOND, ...) 检索两个DATETIME 值之间的秒数。

需要注意的是,INNER JOIN 用于排除任何日期 和时间in 没有对应的日期和时间out

SELECT
   TIMESTAMPDIFF(SECOND, in_time.Date_time, out_time.Date_Time) AS diff_sec,
   in_time.Date_time AS in_date_time,
   out_time.Date_Time AS out_date_time
FROM (
    SELECT
        ID,
        STR_TO_DATE(CONCAT(t.Day, ' ', t.Hour), '%Y-%m-%d %H:%i:%s') AS Date_Time
    FROM table_name AS t
    WHERE t.Status = 'in'
    ORDER BY ID ASC
) AS in_time
INNER JOIN (
    SELECT
        ID,
        STR_TO_DATE(CONCAT(t.Day, ' ', t.Hour), '%Y-%m-%d %H:%i:%s') AS Date_Time
    FROM table_name AS t
    WHERE t.Status = 'out'
    ORDER BY ID ASC
) AS out_time
ON out_time.ID = (
    SELECT MIN(ID)
    FROM table_name AS t
    WHERE t.Status = 'out'
    AND t.ID > in_time.ID
)

数据透视表结果

| diff_sec | in_date_time        | out_date_time       |
| -------- | ------------------- | ------------------- |
| 1125     | 2021-03-04 19:45:05 | 2021-03-04 20:03:50 |
| 17       | 2021-03-04 20:04:34 | 2021-03-04 20:04:51 |
| 10500    | 2021-03-04 21:04:59 | 2021-03-04 23:59:59 |
| 48       | 2021-03-04 22:08:07 | 2021-03-04 22:08:55 |
| 16717    | 2021-03-05 14:46:32 | 2021-03-05 19:25:09 |

以秒为单位的持续时间总和

在 PHP 中,您可以使用 array_sum()array_column(..., 'diff_sec') 检索 数据透视表结果 查询,以获取持续时间的总和(以秒为单位)。

示例:https://3v4l.org/Af7Cn

$diff = array_sum(array_column($timesheets, 'diff_sec'));
$tmins = $diff / 60;
$hours = floor($tmins / 60);
$mins = $tmins%60;

echo "$hours hours and $mins minutes";
// 7 hours and 53 minutes

在 SQL 中将 SUM() 包裹在生成的 TIMESTAMPDIFF() 查询周围,以从所有 TIMESTAMPDIFF 值中检索总秒数 (28407)。

SELECT
   SUM(TIMESTAMPDIFF(SECOND, in_time.Date_time, out_time.Date_Time)) AS total_sec
FROM (
    SELECT
        ID,
        STR_TO_DATE(CONCAT(t.Day, ' ', t.Hour), '%Y-%m-%d %H:%i:%s') AS Date_Time
    FROM table_name AS t
    WHERE t.Status = 'in'
    ORDER BY ID ASC
) AS in_time
INNER JOIN (
    SELECT
        ID,
        STR_TO_DATE(CONCAT(t.Day, ' ', t.Hour), '%Y-%m-%d %H:%i:%s') AS Date_Time
    FROM table_name AS t
    WHERE t.Status = 'out'
    ORDER BY ID ASC
) AS out_time
ON out_time.ID = (
    SELECT MIN(ID)
    FROM table_name AS t
    WHERE t.Status = 'out'
    AND t.ID > in_time.ID
)

hh:mm:ss 持续时间

SEC_TO_TIME() 可用于以hh:mm:ss 格式显示所产生的总秒数中的小时、分钟和秒 (07:53:27) 的持续时间。

SELECT
    SEC_TO_TIME(SUM(TIMESTAMPDIFF(SECOND, in_time.Date_time, out_time.Date_Time))) AS duration
FROM (
   SELECT
      ID,
      STR_TO_DATE(CONCAT(t.Day, ' ', t.Hour), '%Y-%m-%d %H:%i:%s') AS Date_Time
   FROM table_name AS t
   WHERE t.Status = 'in'
   ORDER BY ID ASC
) AS in_time
INNER JOIN (
   SELECT
       ID,
       STR_TO_DATE(CONCAT(t.Day, ' ', t.Hour), '%Y-%m-%d %H:%i:%s') AS Date_Time
   FROM table_name AS t
   WHERE t.Status = 'out'
   ORDER BY ID ASC
) AS out_time
ON out_time.ID = (
   SELECT MIN(ID)
   FROM table_name AS t
   WHERE t.Status = 'out'
   AND t.ID > in_time.ID
);

DB-Fiddle 上的示例

格式化持续时间

TIME_FORMAT() 可以与您想要的format 一起使用以优化持续时间输出。

TIME_FORMAT(SEC_TO_TIME(...), '%H hours and %i minutes') AS duration_formatted
# 07 hours and 53 minutes

或者在 PHP 中使用explode(':', ...) 来根据需要解析返回的持续时间。

例如https://3v4l.org/9miQT

vprintf('%d hours and %d minutes', explode(':', $timesheet['duration'], 2));
// 7 hours and 53 minutes

【讨论】:

    【解决方案2】:

    您的数据看起来顺序相反。您可以按升序查询数据,也可以使用array_reverse()

    $timesheets = array_reverse($timesheets);
    

    然后您可以将inout 时间与array_chunk() 组合在一起。

    $chunks = array_chunk($timesheets, 2);
    

    然后你可以用array_map()计算inout时间的差。

    $diffs = array_map(function ($chunk) {
        return strtotime($chunk[1][1]) - strtotime($chunk[0][1]);
    }, $chunks);
    

    并将时间差与array_sum()相加。

    $sum = array_sum($diffs);
    

    然后打印出时间。

    $seconds = $sum % 60;
    $minutes = ($sum / 60) % 60;
    $hours = (int) ($sum / 3600);
    
    echo "$hours hours $minutes minutes $seconds seconds";
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-17
      • 1970-01-01
      • 2019-02-22
      • 2016-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-17
      相关资源
      最近更新 更多