Search code examples
phpdatetimetime

Hour difference between 2 DateTime objects in Decimal Format


I have 2 DateTime objects, I need to calculate the difference between them in hours in decimal format. The hard part is making sure the result is storing the value to 2 decimal places.

$datetime1 = new DateTime("2017-09-01 23:00:00");
$datetime2 = new DateTime();
$difference = $datetime2->diff($datetime1);

How to keep the value to 2 decimal places?


Solution

  • DateTime::diff()

    DateTime::diff returns DaterInterval that has an integer number value for each individual time related property. To determine the total hours from the ::diff(), perform math on each of the individual properties (microseconds f, seconds s, minutes i, hours h, and total days days), with some considerations.

    The days property does not account for increments less than a day, as they are accumulated to and removed from the lesser properties and then is rounded down.

    This means $diff->h will never be greater than 23. While $diff->s and $diff->i will never be greater than 59. Where $diff->days will contain the total days between the two dates and is not to be confused with $diff->d, which is the incremental number of days before rolling into a month.

    Then just round() or format (sprintf, substr, etc) the resulting value to the desired precision.

    Example: https://3v4l.org/atcqG

    $start = new DateTime('2017-09-01 23:00:00');
    $stop = new DateTime('2017-09-02 01:34:00');
    $diff = $stop->diff($start);
    $hours = ($diff->s / 3600) + ($diff->i / 60) + $diff->h + ($diff->days * 24);
    $hours += $diff->f / 3.6e+9; // PHP 7.1+ 
    
    echo round($hours, 2); // 2.57
    

    In PHP 7.1+ you also account for microseconds by adding $diff->f / 3.6e+9.


    Unix Timestamp

    A more simplistic approach would be to subtract the start/stop Unix timestamps, which will retrieve the total number of seconds between the two dates. Then divide the resulting value by the number of seconds in an hour (3600).

    Example: https://3v4l.org/SbjEU

    $start = new DateTime('2017-09-01 23:00:00');
    $stop = new DateTime('2017-09-02 01:34:00');  
    $hours = ($stop->getTimestamp() - $start->getTimestamp()) / 3600;
    
    echo round($hours, 2); // 2.57
    

    Or using strtotime instead of DateTime

    Example: https://3v4l.org/3p1V3

    $start = strtotime('2017-09-01 23:00:00');
    $stop = strtotime('2017-09-02 01:34:00');
    $hours = ($stop - $start) / 3600;
    
    echo round($hours, 2); // 2.57
    

    DatePeriod

    A DatePeriod object can be used as an alternative approach to retrieving the number of seconds between the two dates, similarly to using Unix timestamps above, by passing the object a DateInterval argument of 1 second (PT1S) and counting the number of iterations available in the result by using iterator_count().

    Example: https://3v4l.org/h2sID

    $start = new DateTime('2017-09-01 23:00:00');
    $stop = new DateTime('2017-09-02 01:34:00');
    $hours = iterator_count(new DatePeriod($start, new DateInterval('PT1S'), $stop)) / 3600;
    
    echo round($hours, 2); // 2.57