I want to calculate time not spent between certain hours in time periods. You can think it like a work overtime calculator.
Inputs are:
//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"
In this case, the answer should be 5 hours. (Can be in seconds)
Entrance and exit time can be longer (few days) or shorter (same day). And start time and end time can be on the same day. (for example: 09:00-10:00)
I checked this question but code is not working correctly if time period includes midnight.
Thanks for your answers.
Here's a code for you, a code which calculate the time and:
Does not not use any loops, which are very inefficient and not really needed. It calculates the time by minutes to be able to handle accurately any hour, such as 14:27. The code deals with the over midnight working hour times. Returns a nice array with relevant data, which can be helpful for debugging. the result is in ['total_in_minutes'] in minutes, but also in ['total_in_hours'] in hours .Output:
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
)
Code:
$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);
}
If you can get the date time for starttime
and endtime
the small function getTimestampDiff
will do what you need.
//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);
Output:
Time worked in minutes: 300
Time worked in hours: 5