PHP 查找日期之间特定时间段内未花费的时间
PHP finding time not spent in certain time period between dates
我想计算时间段内特定时间之间未花费的时间。
你可以把它想象成一个加班计算器。
输入是:
//This two is work start and end time.
$starttime="22:00";
$endtime="02:00";
//This two is person's entrance and exit time.
$entrance="2016-06-24 20:00:00"
$exit="2016-06-25 05:00:00"
在这种情况下,答案应该是 5 小时。 (可以以秒为单位)
进出时间可以更长(几天)或更短(同一天)。并且开始时间和结束时间可以在同一天。 (例如:09:00-10:00)
我检查了 this 问题,但如果时间段包括午夜,代码将无法正常工作。
感谢您的回答。
如果您可以获得 starttime
和 endtime
的日期时间,小函数 getTimestampDiff
将满足您的需要。
//This two is work start and end time.
$starttime = "2016-06-24 22:00";
$endtime = "2016-06-25 02:00";
//This two is person's entrance and exit time.
$entrance = "2016-06-24 20:00:00";
$exit = "2016-06-25 05:00:00";
function getTimestampDiff($startTime, $endTime)
{
$start = new DateTime($startTime);
$end = new DateTime($endTime);
return $end->getTimestamp() - $start->getTimestamp();
}
$timeIdle = getTimestampDiff($starttime, $endtime);
$timeWorking = getTimestampDiff($entrance, $exit);
$res = ($timeWorking - $timeIdle);
echo sprintf("Time worked in minutes: %d<br />", $res / 60);
echo sprintf("Time worked in hours: %d", $res / 60 / 60);
输出:
Time worked in minutes: 300
Time worked in hours: 5
这是给你的代码,一个计算时间的代码,并且:
不使用任何循环,这是非常低效的,并不是真正需要的。
以分钟计算时间,可以准确处理任何一个小时,如14:27。
该代码处理超过午夜的工作时间。
Returns 一个包含相关数据的漂亮数组,有助于调试。
结果在 ['total_in_minutes'] 分钟内,但也在 ['total_in_hours'] 小时内。
输出:
Array
(
[total_in_hours] => 5
[total_in_minutes] => 300
[days] => 1
[is_over_midnight] => 1
[total_min_first_day] => 120
[total_min_middle_days] => 0
[total_min_last_day] => 180
)
代码:
$starttime="22:00";
$endtime="02:00";
$entrance="2016-06-24 20:00:00";
$exit="2016-06-25 05:00:00";
$time = calc_overtime($starttime, $endtime, $entrance, $exit);
print_r($time);
function calc_overtime($starttime, $endtime, $entrance, $exit){
$total_days = date("d", strtotime($exit)) - date("d", strtotime($entrance));
$working_hours[0] = array('start'=>get_minutes($starttime), 'end'=>get_minutes($endtime));
$working_hours_a_day = ($working_hours[0]['end']-$working_hours[0]['start']);
$over_midnight = (get_minutes($endtime)<get_minutes($starttime))?1:0;
// split into two working hours which end>start in both
if ($over_midnight) {
$working_hours[0] = array('start'=>get_minutes($starttime), 'end'=> 24*60);
$working_hours[1] = array('start'=>0, 'end'=>get_minutes($endtime));
$working_hours_a_day = ($working_hours[0]['end']-$working_hours[0]['start'])+($working_hours[1]['end']-$working_hours[1]['start']);
}
// only one day - came and left the same day
if ($total_days == 0){
$total_overtime = calc_overtime_one_day(get_minutes($exit)-get_minutes($entrance), get_minutes($entrance), get_minutes($exit), $working_hours[0]['start'], $working_hours[0]['end']);
$total_overtime = $over_midnight? calc_overtime_one_day($total_overtime, get_minutes($entrance), get_minutes($exit), $working_hours[1]['start'], $working_hours[1]['end']): $total_overtime;
return array('total_in_hours'=>$total_overtime/60 ,'total_in_minutes'=>$total_overtime , 'days' => $total_days, 'is_over_midnight'=>$over_midnight) ;
}
// More than one day
$total_overtime_first_day = calc_overtime_one_day(24*60-get_minutes($entrance), get_minutes($entrance), 24*60, $working_hours[0]['start'], $working_hours[0]['end']);
$total_overtime_first_day = $over_midnight ? calc_overtime_one_day($total_overtime_first_day, get_minutes($entrance), 24*60, $working_hours[1]['start'], $working_hours[1]['end']): $total_overtime_first_day;
$total_overtime_last_day = calc_overtime_one_day(get_minutes($exit)-0, 0, get_minutes($exit), $working_hours[0]['start'], $working_hours[0]['end']);
$total_overtime_last_day = $over_midnight ? calc_overtime_one_day($total_overtime_last_day, 0, get_minutes($exit), $working_hours[1]['start'], $working_hours[1]['end']):$total_overtime_last_day;
$total_middle_days = ($total_days>1)? ((24*60-$working_hours_a_day)*($total_days-1)):0;
$total = $total_overtime_first_day + $total_overtime_last_day + $total_middle_days;
return array('total_in_hours'=>$total/60 , 'total_in_minutes'=>$total ,
'days' => $total_days, 'is_over_midnight'=>$over_midnight, 'total_min_first_day'=>$total_overtime_first_day,
'total_min_middle_days'=>$total_middle_days, 'total_min_last_day'=>$total_overtime_last_day) ;
}
function calc_overtime_one_day($current_minutes, $entrance, $exit, $gap_start, $gap_end){
if ($entrance>=$gap_end || $exit <= $gap_start) { return $current_minutes; }
$remove_end = $gap_end;
$remove_start = $gap_start;
if ($entrance>=$gap_start) { $remove_start = $entrance; }
if ($exit<=$gap_end) {$remove_end = $exit;}
if ($exit<=$gap_end) {$remove_end = $exit;}
return $current_minutes - ($remove_end-$remove_start);
}
function get_minutes($string_time){
$timestamp = strtotime($string_time);
return 60*date("H", $timestamp)+1*date("i", $timestamp);
}
我想计算时间段内特定时间之间未花费的时间。 你可以把它想象成一个加班计算器。
输入是:
//This two is work start and end time.
$starttime="22:00";
$endtime="02:00";
//This two is person's entrance and exit time.
$entrance="2016-06-24 20:00:00"
$exit="2016-06-25 05:00:00"
在这种情况下,答案应该是 5 小时。 (可以以秒为单位)
进出时间可以更长(几天)或更短(同一天)。并且开始时间和结束时间可以在同一天。 (例如:09:00-10:00)
我检查了 this 问题,但如果时间段包括午夜,代码将无法正常工作。
感谢您的回答。
如果您可以获得 starttime
和 endtime
的日期时间,小函数 getTimestampDiff
将满足您的需要。
//This two is work start and end time.
$starttime = "2016-06-24 22:00";
$endtime = "2016-06-25 02:00";
//This two is person's entrance and exit time.
$entrance = "2016-06-24 20:00:00";
$exit = "2016-06-25 05:00:00";
function getTimestampDiff($startTime, $endTime)
{
$start = new DateTime($startTime);
$end = new DateTime($endTime);
return $end->getTimestamp() - $start->getTimestamp();
}
$timeIdle = getTimestampDiff($starttime, $endtime);
$timeWorking = getTimestampDiff($entrance, $exit);
$res = ($timeWorking - $timeIdle);
echo sprintf("Time worked in minutes: %d<br />", $res / 60);
echo sprintf("Time worked in hours: %d", $res / 60 / 60);
输出:
Time worked in minutes: 300
Time worked in hours: 5
这是给你的代码,一个计算时间的代码,并且:
输出:
Array
(
[total_in_hours] => 5
[total_in_minutes] => 300
[days] => 1
[is_over_midnight] => 1
[total_min_first_day] => 120
[total_min_middle_days] => 0
[total_min_last_day] => 180
)
代码:
$starttime="22:00";
$endtime="02:00";
$entrance="2016-06-24 20:00:00";
$exit="2016-06-25 05:00:00";
$time = calc_overtime($starttime, $endtime, $entrance, $exit);
print_r($time);
function calc_overtime($starttime, $endtime, $entrance, $exit){
$total_days = date("d", strtotime($exit)) - date("d", strtotime($entrance));
$working_hours[0] = array('start'=>get_minutes($starttime), 'end'=>get_minutes($endtime));
$working_hours_a_day = ($working_hours[0]['end']-$working_hours[0]['start']);
$over_midnight = (get_minutes($endtime)<get_minutes($starttime))?1:0;
// split into two working hours which end>start in both
if ($over_midnight) {
$working_hours[0] = array('start'=>get_minutes($starttime), 'end'=> 24*60);
$working_hours[1] = array('start'=>0, 'end'=>get_minutes($endtime));
$working_hours_a_day = ($working_hours[0]['end']-$working_hours[0]['start'])+($working_hours[1]['end']-$working_hours[1]['start']);
}
// only one day - came and left the same day
if ($total_days == 0){
$total_overtime = calc_overtime_one_day(get_minutes($exit)-get_minutes($entrance), get_minutes($entrance), get_minutes($exit), $working_hours[0]['start'], $working_hours[0]['end']);
$total_overtime = $over_midnight? calc_overtime_one_day($total_overtime, get_minutes($entrance), get_minutes($exit), $working_hours[1]['start'], $working_hours[1]['end']): $total_overtime;
return array('total_in_hours'=>$total_overtime/60 ,'total_in_minutes'=>$total_overtime , 'days' => $total_days, 'is_over_midnight'=>$over_midnight) ;
}
// More than one day
$total_overtime_first_day = calc_overtime_one_day(24*60-get_minutes($entrance), get_minutes($entrance), 24*60, $working_hours[0]['start'], $working_hours[0]['end']);
$total_overtime_first_day = $over_midnight ? calc_overtime_one_day($total_overtime_first_day, get_minutes($entrance), 24*60, $working_hours[1]['start'], $working_hours[1]['end']): $total_overtime_first_day;
$total_overtime_last_day = calc_overtime_one_day(get_minutes($exit)-0, 0, get_minutes($exit), $working_hours[0]['start'], $working_hours[0]['end']);
$total_overtime_last_day = $over_midnight ? calc_overtime_one_day($total_overtime_last_day, 0, get_minutes($exit), $working_hours[1]['start'], $working_hours[1]['end']):$total_overtime_last_day;
$total_middle_days = ($total_days>1)? ((24*60-$working_hours_a_day)*($total_days-1)):0;
$total = $total_overtime_first_day + $total_overtime_last_day + $total_middle_days;
return array('total_in_hours'=>$total/60 , 'total_in_minutes'=>$total ,
'days' => $total_days, 'is_over_midnight'=>$over_midnight, 'total_min_first_day'=>$total_overtime_first_day,
'total_min_middle_days'=>$total_middle_days, 'total_min_last_day'=>$total_overtime_last_day) ;
}
function calc_overtime_one_day($current_minutes, $entrance, $exit, $gap_start, $gap_end){
if ($entrance>=$gap_end || $exit <= $gap_start) { return $current_minutes; }
$remove_end = $gap_end;
$remove_start = $gap_start;
if ($entrance>=$gap_start) { $remove_start = $entrance; }
if ($exit<=$gap_end) {$remove_end = $exit;}
if ($exit<=$gap_end) {$remove_end = $exit;}
return $current_minutes - ($remove_end-$remove_start);
}
function get_minutes($string_time){
$timestamp = strtotime($string_time);
return 60*date("H", $timestamp)+1*date("i", $timestamp);
}