2012-07-19 9 views
22

Quiero añadir dos intervalos de fechas para calcular la duración total en horas y minutos, de hecho, yo quiero realizar addittion como se muestra a continuación:¿Cómo podemos añadir dos intervalos de fechas en 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; 

alguna idea de cómo realizar este tipo de adición intervalo para obtener la suma de los dos intervalos en horas y minutos en total formato en PHP

Respuesta

33

PHP no tiene la sobrecarga de operadores * por lo + con objetos hace que PHP intente que convertirlos a primera cadena, pero DateInterval hace no es compatible con eso:

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

lugar es necesario crear una nueva DateTime objeto, a continuación, utilizar la función add añadir los intervalos y, finalmente, mostrar la diferencia en el punto de referencia:

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

completa Exmaple/(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"; 

también puede ser que desee considerar el mirar cómo DateInterval almacena sus valores y luego extender f roma para hacer tu propio cálculo. El siguiente ejemplo (Demo) es áspera, que no toma en cuenta the inverted thingy, lo hace not (re)set $days to false y no he comprobado/probado la especificación ISO de the period specifier on creation pero creo que es suficiente para mostrar la idea:

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

* Si escribe una extensión de PHP, en realidad es posible (al menos tipo de).

+0

Algunos más experimentos: http://codepad.viper-7.com/Lh2DtL ([GIST] (https: // GIST .github.com/3142405)) – hakre

+0

Hola, ¿y si, con tu solución, el total es mayor a 60 segundos, 60 minutos, 24 horas, ... etc.? :) – Talus

+0

@Talus: Vea lo esencial, no es que sea perfecto, pero muestra cómo puede manejar eso. – hakre

6

Esta función le permite combinar cualquier número de 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

Esto no funcionó para mí, '$ endTime' creo que debido a' DateTimeImmutable'.Funcionó cuando cambié 'new DateTimeImmutable' por' new DateTime() ' – Gyfis

+1

@Gyfis Strange, funciona muy bien para mí. Recuerde que Immutables devolverá una nueva instancia cuando se modifique. –

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>"; 
Cuestiones relacionadas