1


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.

Community
  • 1
  • 1
W. Mole
  • 21
  • 3
  • 2
    Possible duplicate of [PHP find the days until a date](http://stackoverflow.com/questions/19519851/php-find-the-days-until-a-date) – wazelin Jun 24 '16 at 13:03
  • Use `strtotime();`and calculate the difference? – KIMB-technologies Jun 24 '16 at 13:05
  • I can calculate difference, I also can calculate days between dates. To clarify, I do not want to include specific time periods, also entrance or exit time can be in work hours. – W. Mole Jun 24 '16 at 13:09

2 Answers2

0

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
cb0
  • 8,415
  • 9
  • 52
  • 80
  • Thanks for the answer, $starttime and $endtime are actually fixed values. There can be for example, 3 days between entrance and exit and I should count all the time that is not within the work start and end time. When I set start 10:00, end 15:00, entrance 09:00 and exit to 11:00 (same day) I should get 1 hour overtime work. But I get -3 hours with your code. But it's a good starting point, maybe I should iterate through every day and calculate day by day? – W. Mole Jun 24 '16 at 14:23
0

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);
    }
    
  • Elad
    • 84
    • 3