phpdatetimedateinterval

PHP adding two DateInterval-objects together


I'm crunching some numbers from a time recording experiment using PHP. How do I add two DateInterval-objects together?

One of the DateIntervals are found as such (the difference between two DateTime-objects):

$start_stamp = new \DateTime( '2017-09-01T07:10' ); // DateTime-object
$end_stamp   = new \DateTime( '2017-09-01T07:10' ); // DateTime-object
$duration    = $start_stamp->diff( $end_stamp ); // DateInterval-object

The other DateInterval is simply define as such:

$abc = new \DateInterval( 'PT1H' ); // DateInterval with duration of 1 hour

I've read a couple of places, that one should convert my DateIntervals to DateTime-objects and then use the $dateTimeObject->add(...)-function. But that seems silly to me. It is a duration, - so why should I convert it to something that it isn't is, in order to handle it properly.

I wrote below-written function to solve the problem, - but it seems clumsy. Can it be written better - or are there a better way of summing up two DateInterval-objects?

function sumDateIntervals($dateinterval_one, $dateinterval_two)
{
  $d1_years = $dateinterval_one->y;
  $d1_months = $dateinterval_one->m;
  $d1_days = $dateinterval_one->d;
  $d1_hours = $dateinterval_one->h;
  $d1_minutes = $dateinterval_one->i;
  $d1_seconds = $dateinterval_one->s;
  $d1_float = $dateinterval_one->f;

  $d2_years = $dateinterval_two->y;
  $d2_months = $dateinterval_two->m;
  $d2_days = $dateinterval_two->d;
  $d2_hours = $dateinterval_two->h;
  $d2_minutes = $dateinterval_two->i;
  $d2_seconds = $dateinterval_two->s;
  $d2_float = $dateinterval_two->f;

  $return_dateinterval = new DateInterval( 
                     'P' . ( string ) ( $d1_years + $d2_years ) . 'Y' 
                     . ( string ) ( $d1_months + $d2_months ) . 'M' 
                     . ( string ) ( $d1_days + $d2_days ) . 'DT' 
                     . ( string )  ($d1_hours + $d2_hours ) . 'H' 
                     . ( string ) ( $d1_minutes + $d2_minutes ) . 'M' 
                     . ( string ) ($d1_seconds + $d2_seconds ) . 'S' );

  return $return_dateinterval;
}

Solution

  • 2021 Update

    Almost four years wiser, I think the best way is to let PHP compute the sum and normalize the fields in the process:

    function sumDateIntervals(DateInterval $a, DateInterval $b)
    {
      $base = new DateTimeImmutable();
    
      return $base->add($a)->add($b)->diff($base);
    }
    

    Check it online.

    The originally accepted answer

    To me, your solution looks like the best way to implement this functionality.

    There is no need to explicitly convert the sums to strings (PHP does it anyway). If you want to make it more readable you can use sprintf() to produce the string and shorter names for the arguments:

    function sumDateIntervals(DateInterval $a, DateInterval $b)
    {
        return new DateInterval(sprintf('P%dY%dM%dDT%dH%dM%dS',
            $a->y + $b->y,
            $a->m + $b->m,
            $a->d + $b->d,
            $a->h + $b->h,
            $a->i + $b->i,
            $a->s + $b->s
        ));
    }