计算 PHP 中的工作时间,包括刹车

Calculate time worked including brakes in PHP

我正在努力编写一个 PHP 函数来计算两个小时(减去刹车)之间的时差,结果将采用十进制格式。我的输入是 24 小时格式的字符串 (hh:mm):

$start = '07:00'; //started at 7 after midnight
$brake = '01:30'; //1 hour and 30 minutes of brake
$finish = '15:00'; //finished at 3 afternoon
//the desired result is to print out '6.5'

示例 2

$start = '19:00'; //started late afternoon
$brake = '00:30'; //30 minutes of brake
$finish = '03:00'; //finished at 3 after midnight
//the desired result is to print out '7.5'

我曾经在 MS Excel 中使用以下公式,效果很好:

=IF(D12>=F12,((F12+1)-D12-E12)*24,(F12-D12-E12)*24) '7.5 worked hours

哪里
D12 - 开始时间 '19:00
F12 - 结束时间 '03:00
E12 - 刹车时间 '00:30

我尝试使用 strtotime() 但没有成功。我的 PHP 版本是 5.4.45。请帮助

为此,请将字符串时间转换为 unix 时间戳。这是自 unix 纪元以来的整数秒数(00:00:00 协调世界时 (UTC),星期四,1970 年 1 月 1 日,减去自那时以来发生的闰秒数).计算一下,然后使用 Date() 函数将其格式化回您的起始格式:

<?php

$start = '19:00'; //started late afternoon
$break = '00:30'; //30 minutes of brake
$finish = '03:00'; //finished at 3 after midnight

//get the number of seconds for which we took a $break
//do this by converting break to unix timestamp, then extracting the hour and multiplying by 360
//and do the same extracting minutes and multiplying by 60
$breaktime = date("G",strtotime($break))*60*60 + date("i",strtotime($break))*60;

//get start time
$unixstart=strtotime($start);

//get finish time. Add a day if finish is tomorrow
if (strtotime($finish) < $unixstart) {
    $unixfinish = strtotime('+1 day', strtotime($finish));
} else {
    $unixfinish = strtotime($finish);
}

//figure out time worked
$timeworked = ($unixfinish - $unixstart - $breaktime) / 3600;

echo $timeworked;

?>

另一种方式,使用DateTime。基本上,创建 2 DateTime 个具有开始和结束时间的对象。开始时间减去刹车时间,结果减去结束时间。

需要拆分刹车时间才能使用modify()

<?php
$start = '07:00'; //started at 7 after midnight
$brake = '01:30'; //1 hour and 30 minutes of brake
$brakeBits = explode(":", $brake);
$finish = '15:00'; //finished at 3 afternoon
$startDate = \DateTime::createFromFormat("!H:i", $start);
$startDate->modify($brakeBits[0]." hour ".$brakeBits[1]." minutes");
$endDate  = \DateTime::createFromFormat("!H:i", $finish);
$diff = $startDate->diff($endDate);
echo $diff->format("%r%H:%I"); // 06:30

Demo

提供不需要太多数学运算或时间值解析的解决方案。

假设不知道哪一天,我们还可以计算结束时间和开始时间的偏移量,当开始时间是深夜时。

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

$start = '07:00'; //started at 7 after midnight
$break = '01:30'; //1 hour and 30 minutes of brake
$finish = '15:00'; //finished at 3 afternoon

//create the start and end date objects
$startDate = \DateTime::createFromFormat('H:i', $start);
$endDate =  \DateTime::createFromFormat('H:i', $finish);

if ($endDate < $startDate) {
    //end date is in the past, adjust to the next day
    //this is only needed since the day the time was worked is not known
    $endDate->add(new \DateInterval('PT24H'));
}

//determine the number of hours and minutes during the break
$breakPeriod = new \DateInterval(vsprintf('PT%sH%sM', explode(':', $break)));

//increase the start date by the amount of time taken during the break period
$startDate->add($breakPeriod);

//determine how many minutes are between the start and end dates
$minutes = new \DateInterval('PT1M');
$datePeriods = new \DatePeriod($startDate, $minutes, $endDate);

//count the number of minute date periods
$minutesWorked = iterator_count($datePeriods);

//divide the number of minutes worked by 60 to display the fractional hours
var_dump($minutesWorked / 60); //6.5

这将适用于 24 小时内的任何时间值 00:00 - 23:59。如果已知工作时间的日期,则可以修改脚本以允许指定日期并提供更精确的时间安排。