PHP将两个DateInterval对象一起添加

时间:2017-10-15 16:35:57

标签: php datetime dateinterval

我正在使用PHP进行时间记录实验中的一些数字。如何将两个DateInterval对象一起添加?

其中一个DateIntervals就是这样(两个DateTime对象之间的差异):

$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

另一个DateInterval只是这样定义:

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

我读过几个places,应该将我的DateIntervals转换为DateTime对象,然后使用$dateTimeObject->add(...) - 函数。但这对我来说似乎很愚蠢。这是一个持续时间, - 所以我为什么要把它转换成它不是的东西,以便正确处理它。

我写了下面写的函数来解决这个问题,但是看起来很笨拙。可以写得更好 - 还是有更好的方法来总结两个DateInterval对象?

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;
}

2 个答案:

答案 0 :(得分:1)

对我而言,您的解决方案看起来是实现此功能的最佳方式。

无需将总和显式转换为字符串(PHP无论如何都要这样做)。如果您想让它更具可读性,可以使用sprintf()为参数生成字符串和更短的名称:

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
    ));
}

答案 1 :(得分:0)

另一种方法可能是使用魔术__set_state()方法创建一个新的DateInterval,从两个现有区间中的等效属性的总和构建一个属性值数组。

快速而丑陋的代码块(未经测试)以演示此方法:

$properties = ['y' => PHP_INT_MAX,'m' => 12,'d' => 30,'h' => 24,'i' => 60,'s' => 60];


$dti1 = new DateInterval('P1Y7M16DT15H30M15S');
$dti2 = new DateInterval('P2Y8M26DT14H40M55S');

$state = array_fill_keys(array_keys($properties), null);

$carry = 0;
foreach(array_reverse($properties) as $property => $limit) {
    $state[$property] = $dti1->{$property} + $dti2->{$property} + $carry;
    $carry = 0;
    if ($state[$property] > $limit) {
        do {
            $state[$property] -= $limit;
            ++$carry;
        } while ($state[$property] > $limit);
        $state[$property] = $state[$property] % $limit;
    }
}

$newInterval = DateInterval::__set_state($state);

var_dump($newInterval);

需要进行一些清理才能处理day属性,并允许在PHP 7.1中添加的f属性