2012-07-19 59 views
22

添加兩個日期的時間間隔我想補充兩個日期的時間間隔來計算小時和分鐘,其實我想執行addittion總持續時間,如下圖所示:我們如何可以在PHP

$a = new DateTime('14:25'); 
$b = new DateTime('17:30'); 
$interval1 = $a->diff($b); 
echo "interval 1 : " . $interval1->format("%H:%I"); 
echo "<br />"; 

$c = new DateTime('08:00'); 
$d = new DateTime('13:00'); 
$interval2 = $c->diff($d); 
echo "interval 2 : " . $interval2->format("%H:%I"); 
echo "<br />"; 

echo "Total interval : " . $interval1 + $interval2; 

任何想法如何執行這種類型的間隔增加的拿到總小時和分鐘格式的兩個間隔的總和PHP

回答

33

PHP沒有操作符重載*所以+與物體使得PHP試圖給他們先轉換爲字符串,但DateInterval確實不支持:

interval 1: 03:05 
interval 2: 05:00 
Total interval : 08:05 

相反,你需要創建一個新的DateTime對象,然後使用add函數添加間隔,最後顯示的差異參考點:

$e = new DateTime('00:00'); 
$f = clone $e; 
$e->add($interval1); 
$e->add($interval2); 
echo "Total interval : ", $f->diff($e)->format("%H:%I"), "\n"; 

完全〔實施例/(Demo):

$a = new DateTime('14:25'); 
$b = new DateTime('17:30'); 
$interval1 = $a->diff($b); 
echo "interval 1: ", $interval1->format("%H:%I"), "\n"; 

$c = new DateTime('08:00'); 
$d = new DateTime('13:00'); 
$interval2 = $c->diff($d); 
echo "interval 2: ", $interval2->format("%H:%I"), "\n"; 

$e = new DateTime('00:00'); 
$f = clone $e; 
$e->add($interval1); 
$e->add($interval2); 
echo "Total interval : ", $f->diff($e)->format("%H:%I"), "\n"; 

您也可能要考慮尋找如何DateInterval存儲其值,然後延伸˚F從它來做你自己的計算。下面的例子(Demo)是粗糙的,它沒有考慮到the inverted thingy,它not (re)set $days to false和我沒有檢查/測試的the period specifier on creation ISO規範,但我認爲這足以表明這個想法:

class MyDateInterval extends DateInterval 
{ 
    /** 
    * @return MyDateInterval 
    */ 
    public static function fromDateInterval(DateInterval $from) 
    { 
     return new MyDateInterval($from->format('P%yY%dDT%hH%iM%sS')); 
    } 

    public function add(DateInterval $interval) 
    { 
     foreach (str_split('ymdhis') as $prop) 
     { 
      $this->$prop += $interval->$prop; 
     } 
    } 
} 

$a = new DateTime('14:25'); 
$b = new DateTime('17:30'); 
$interval1 = $a->diff($b); 
echo "interval 1: ", $interval1->format("%H:%I"), "\n"; 

$c = new DateTime('08:00'); 
$d = new DateTime('13:00'); 
$interval2 = $c->diff($d); 
echo "interval 2: ", $interval2->format("%H:%I"), "\n"; 

$e = MyDateInterval::fromDateInterval($interval1); 
$e->add($interval2); 
echo "Total interval: ", $e->format("%H:%I"), "\n"; 

*如果你編寫一個PHP擴展,它實際上是可能的(至少排序)。

+0

一些更實驗的結合:http://codepad.viper-7.com/Lh2DtL([要點](https://開頭要點.github.com/3142405)) – hakre 2012-07-19 09:12:38

+0

嗨,如果使用您的解決方案,總數大於60秒,60分鐘,24小時等...怎麼辦? :) – Talus 2013-01-25 14:55:41

+0

@Talus:看到的要點,不是它是完美的,但它顯示了你如何處理。 – hakre 2013-01-25 23:22:36

6

此功能可以讓您任意數量的DateIntervals

/** 
* Combine a number of DateIntervals into 1 
* @param DateInterval $... 
* @return DateInterval 
*/ 
function addDateIntervals() 
{ 
    $reference = new DateTimeImmutable; 
    $endTime = clone $reference; 

    foreach (func_get_args() as $dateInterval) { 
     $endTime = $endTime->add($dateInterval); 
    } 

    return $reference->diff($endTime); 
} 
+0

這對我沒有用,'$ endTime'我認爲是因爲'DateTimeImmutable'。工作時,我改變'新的DateTimeImmutable'爲'新DateTime()' – Gyfis 2015-05-11 10:13:49

+1

@Gyfis奇怪,它對我來說工作得很好。請記住,更改後,Immutables將返回一個新實例。 – 2017-01-16 15:20:18

0
function compare_dateInterval($interval1, $operator ,$interval2){ 
    $interval1_str = $interval1->format("%Y%M%D%H%I%S"); 
    $interval2_str = $interval2->format("%Y%M%D%H%I%S"); 
    switch($operator){ 
     case "<": 
      return $interval1 < $interval2; 
     case ">": 
      return $interval1 > $interval2; 
     case "==" : 
      return $interval1 == $interval2; 
     default: 
      return NULL; 
    } 
} 
function add_dateInterval($interval1, $interval2){ 
    //variables 
    $new_value= []; 
    $carry_val = array(
        's'=>['value'=>60,'carry_to'=>'i'], 
        'i'=>['value'=>60,'carry_to'=>'h'], 
        'h'=>['value'=>24,'carry_to'=>'d'], 
        'm'=>['value'=>12,'carry_to'=>'y'] 
       ); 

    //operator selection 
    $operator = ($interval1->invert == $interval2->invert) ? '+' : '-'; 

    //Set Invert 
    if($operator == '-'){ 
     $new_value['invert'] = compare_dateInterval($interval1,">",$interval2)?$interval1->invert:$interval2->invert; 
    }else{ 
     $new_value['invert'] = $interval1->invert; 
    } 

    //Evaluate 
    foreach(str_split("ymdhis") as $property){ 
     $expression = 'return '.$interval1->$property.' '.$operator.' '.$interval2->$property.';'; 
     $new_value[$property] = eval($expression); 
     $new_value[$property] = ($new_value[$property] > 0) ? $new_value[$property] : -$new_value[$property]; 
     } 

    //carry up 
    foreach($carry_val as $property => $option){ 
     if($new_value[$property] >= $option['value']){ 
      //Modulus 
      $new_value[$property] = $new_value[$property] % $option['value']; 
      //carry over 
      $new_value[$option['carry_to']]++; 
     } 
    } 

    $nv = $new_value; 
    $result = new DateInterval("P$nv[y]Y$nv[m]M$nv[d]DT$nv[h]H$nv[i]M$nv[s]S"); 
    $result->invert = $new_value['invert']; 
    return $result; 
} 

$a = new DateTime('00:0'); 
$b = new DateTime('17:30'); 
$interval1 = $a->diff($b); 
echo "interval 1: ", $interval1->format("%H:%I"), "<br>"; 

$c = new DateTime('08:01:00'); 
$d = new DateTime('13:30:33'); 
$interval2 = $c->diff($d); 
echo "interval 2: ", $interval2->format("%H:%I"), "<br>"; 

$addition = add_dateInterval($interval1,$interval2); 
echo "<pre>"; 
echo var_dump($addition); 
echo "</pre>";