2017-10-15 28 views
1

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

其中DateIntervals被发现作为这样的(两个日期时间,对象之间的差异):

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

回答

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 
    )); 
} 
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财产,并允许这是在加入f财产PHP 7.1

+0

嗯......这似乎挺先进的。有几件事情我不太明白。按照我的建议,这样做的好处是什么? – Zeth

+0

没有什么好处,只是一种不同的方法......尽管'limit'逻辑试图将各个属性值保持在一个适当的范围内,所以你不会得到(例如)PT47H,而是得到'P1DT23H' –