【问题标题】:Calculating time diff across midnight计算午夜的时间差异
【发布时间】:2008-10-05 21:39:33
【问题描述】:

这是我永远无法工作的一件事。
我的问题是检测一天的结束和下一天的开始,然后将差异分成每一天。

假设您想要计算工资率,但它必须跨越午夜。

它也适用于计算在定时系统上运行的时间,或者它应该运行的时间差异。

【问题讨论】:

  • 在计算工资率时,通常只考虑工作时间,想想酒店职员从晚上 10 点开始工作到早上 6 点,他仍然工作 8 小时,即使他的工作时间是跨度的两天
  • 确实如此,但如果一天与另一天的费率不同,您应该使用另一个乘数计算其中一些小时。

标签: algorithm time


【解决方案1】:

我更喜欢在 Unix Epoch 中记录所有时间,这样就很简单了

hoursWorked = ((stopTime - startTime)/60)/60

这是一个完整的解决方案,它使用 PHP,但应该很容易构建到任何语言:

<?php
$startTime = "12/31/2008 22:02"; //No AM/PM we'll use 24hour system
$endTime = "01/01/2009 06:27"; //Again no AM/PM and we spaned the midnight time gap.
/*
Use this to test for a normal shift not ocurring durring midnight.
$startTime = "01/01/2008 06:02"; //No AM/PM we'll use 24hour system
$endTime = "01/01/2008 14:27"; //Again no AM/PM and we spaned the midnight time gap.
*/
$startTime = split(' ', $startTime);
$endTime = split(' ', $endTime);
$startTime[1] = split(':', $startTime[1]);
$endTime[1] = split(':', $endTime[1]);
/*
$startTime[0] contains the date
$startTime[1][0] contains the hours
$startTime[1][1] contains the minutes
same is true for endTime
*/
if($startTime[0] != $endTime[0])
 {
    if(date2epoch($endTime[0]) > date2epoch($startTime[0]))
     {
        $minutesWorked1 = (59 - $startTime[1][1]); //Calculate how many minutes have occured from begining of shift to midnight
        $minutesWorked2 = $endTime[1][1]; //Number of minute from midnight to end of shift
        $hoursWorked1 = (23 - $startTime[1][0]);//Number of hours from start of shift to midnight
        $hoursWorked2 = $endTime[1][0];//Number of minutes from midnight to end of shift
        echo 'Before midnight you worked ' . $hoursWorked1 . ':' . $minutesWorked1 . "\nAfter midnight you worked " . $hoursWorked2 . ':' . $minutesWorked2 . '.';
     }
    else 
     {
        //SOMETHING MAJOR BAD HAS HAPPENED WHILE LOGGING THE CLOCKINS AND CLOCKOUTS
     }
 }
else 
 {
    echo 'Today you worked ' . ($endTime[1][0] - $startTime[1][0]) . ':' . ($endTime[1][1] - $startTime[1][1]);
 }
function date2epoch($date, $format='m/d/Y')
 {
    $date = split('/', $date);
    return mktime('0', '0', '0', $date[0], $date[1], $date[2]);
 }
?>

【讨论】:

  • 我已经编辑了我的问题以澄清问题。你能重新表述你的答案吗?
  • 顺便说一句:PHP 只有在糟糕的程序员构建时才是糟糕的。
【解决方案2】:

在开始和结束时间是包含日期和时间的数据结构的系统中,这显然是一个微不足道的问题。但是有很多系统不这样做。计时系统有一个包含日期、开始时间和结束时间的记录是很常见的。在这种情况下,问题就不那么简单了。

我认为您要问两个问题:

  1. 如何判断时间跨度是否超过午夜?
  2. 如果时间跨度超过午夜,第一天发生了多少时间,第二天发生了多少时间?

第一个问题很容易回答:如果结束时间早于开始时间,则时间跨度已超过午夜。

如果是这种情况,那么您需要计算两个金额。日期发生的时间跨度量是开始时间和午夜之间的时间。下一个日期发生的时间跨度是午夜和结束时间(即结束时间)之间的时间。

【讨论】:

  • 感谢您澄清我自己的问题,但这正是我想要的!
【解决方案3】:

如果你有可用的日期,你应该使用日期+时间的组合,这不会有问题。

如果您知道时间跨度将少于 24 小时:

if endtime < starttime then endtime = endtime + 24 hours

【讨论】:

  • 即使您没有日期,这仍然可以正常工作。午夜之后的时间可以被视为“加 24 小时”。从晚上 11:30 (23:30) 到早上 5:30 (5:30 + 24:00 = 29:30) 很容易计算。
【解决方案4】:

在大多数语言中,日期/日期时间/等。类有这样的方法。使用这些时,最佳做法是在执行算术之前将所有日期转换为 UTC。

例如,C#:

// In UTC, preferably
DateTime ClockIn;
DateTime ClockOut;

ClockIn = ...;
ClockOut = ...;

TimeSpan TimeWorked = ClockOut.Subtract(ClockIn);
float HoursWorked = TimeWorked.TotalHours();

【讨论】:

    【解决方案5】:

    如果两个时间不在同一个时区,您需要在计算之前将它们转换为 UTC :) 此处可能不适用,但这是一个常见问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-28
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多