4

I'm trying to calculate the shift patterns of people who work here, subtracting the start time from the end time works for the most part, but not if they're working overnight. For example someone working from 10pm to 6am would be displayed as:

22:00 - 06:00

I'd like that to return 8 hours, but I just can't figure out the best way of doing it.

Annoyingly, I'm then going to have to do the exact same thing in Javascript, so I hope I can get my head around the logic for this. Taking away one date from the other just doesn't work in this case...

Any help would be much appreciated, thank you!

Nick
  • 3,745
  • 20
  • 56
  • 75

6 Answers6

8
function timeDiff($firstTime,$lastTime) {
    $firstTime=strtotime($firstTime);
    $lastTime=strtotime($lastTime);
    $timeDiff=$lastTime-$firstTime;
    return $timeDiff;
}

echo (timeDiff("10:00","12:00")/60)/60;

Originally wrote this here: https://ataiva.com/how-to-get-the-hours-difference-in-hhmm-format-in-php/

AO_
  • 2,573
  • 3
  • 30
  • 31
  • This is probably my favourite solution - simple and returns the date in a nice format, many thanks to everyone though :) – Nick Apr 27 '12 at 14:58
  • 1
    @Nick: Be aware that this solution can give unexpected results depending on your geographic location and the current date if you are unlucky. The ending paragraph of my answer explains why. – Jon Apr 27 '12 at 16:36
5

Old school, with string manipulation and math:

$input = '22:00 - 06:00';
preg_match('/(\d+):(\d+)\D*(\d+):(\d+)/', $input, $matches);
list(, $startHour, $startMin, $endHour, $endMin) = $matches;
$totalMinutes = ($endHour * 60 + $endMin - $startHour * 60 + $startMin + 1440) % 1440;
$hours = floor($totalMinutes / 60);
$mins = $totalMinutes % 60;

echo "works for $hours hours, $mins minutes";

With date/time functions:

$input = '22:00 - 06:00';
list($start, $end) = array_map('trim', explode('-', $input));
$start = new DateTime($start.'+00:00');
$end = new DateTime($end.'+00:00');
if ($start > $end) $start->sub(new DateInterval('P1D'));
$interval = $end->diff($start);
echo "works for ".$interval->h." hours, ".$interval->m." minutes";

Devilish gotcha for any solution using date/time functions:

If you do not explicitly specify the offset for $start and $end, and we are talking about a night shift, and the code is run on the day where daylight savings time starts or ends the results would be off by whatever the DST offset is.

This is true for any solution that uses DateTime, strtotime, etc.

Jon
  • 428,835
  • 81
  • 738
  • 806
3

without some date function:

$start = '22:00';
$end = '06:00';

$getnum = function($value) {
    $pieces = explode(':', $value);
    if(count($pieces) > 0) {
        return (intval($pieces[0])*60)+intval($pieces[1]);
    }

    return 0;
};

$start_num = $getnum->__invoke($start);
$end_num = $getnum->__invoke($end);

$diff = max($start_num, $end_num) - min($end_num, $start_num);

echo intval($diff / 60).'.'.($diff % 60).' hours';
silly
  • 7,789
  • 2
  • 24
  • 37
2

You can use the function mktime (http://php.net/manual/en/function.mktime.php) to return the number of seconds and subtract the two dates in integer format.

<?php
   $date1=mktime(1, 2, 3, 4, 5, 2006);
   $date2=mktime(1, 2, 3, 4, 5, 2008);
   $diference=$date2-$date1;

   echo $diference

   ?>
Nauber
  • 21
  • 1
1

Working AND most easy sample :

$start = 22;
$end = 6;

if ($start > $end) {
    $end += 24;
}

$duration = $end - $start;

echo 'Duration: ' . $duration . 'hours.';
adrien
  • 4,399
  • 26
  • 26
-1

You can look into date_diff, which is an alias of this function:

http://www.php.net/manual/en/datetime.diff.php

MySQL also has a DATEDIFF() function, so if you are grabbing them from a database you can do it directly from SQL (I know you didn't specify, but I just wanted to mention this).

Logan Serman
  • 29,447
  • 27
  • 102
  • 141