2012-07-19 13 views
22

voglio aggiungere due intervalli di data per calcolare la durata totale in ore e minuti, infatti, voglio eseguire addittion come illustrato di seguito:Come possiamo aggiungere due intervalli di data in 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; 

Qualsiasi idea di come eseguire questo tipo di intervallo aggiunta per ottenere la somma dei due intervalli in ore e minuti formato totale in PHP

risposta

33

PHP ha nessun sovraccarico operatore * così + con oggetti rende PHP provare a convertirli in stringa prima, ma DateInterval fa Non supportarlo:

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

Invece è necessario creare un nuovo DateTime oggetto, quindi utilizzare la funzione add per aggiungere gli intervalli e, infine, visualizzare la differenza dal punto di riferimento:

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

si potrebbe anche prendere in considerazione cercando how DateInterval memorizza i suoi valori e quindi estendere f rom per fare il calcolo tuo. Il seguente esempio (Demo) è grezzo, esso non tiene conto the inverted thingy, lo fa not (re)set $days to false e non ho controllato/testata la specifica ISO di the period specifier on creation ma penso che è sufficiente a mostrare l'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"; 

* Se si scrive un'estensione PHP, in realtà è possibile (almeno in ordine).

+0

Alcuni altri esperimenti: http://codepad.viper-7.com/Lh2DtL ([gist] (https: // Gist .github.com/3142405)) – hakre

+0

Ciao, e se, con la tua soluzione, il totale è superiore a 60 secondi, 60 minuti, 24 ore, ... ecc.? :) – Talus

+0

@Talus: guarda il senso, non che è perfetto, ma mostra come puoi gestirlo. – hakre

6

Questa funzione consente di combinare un numero qualsiasi di 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

Questo non ha funzionato per me, '$ endTime' penso per il' DateTimeImmutable'.Ha funzionato quando ho cambiato 'new DateTimeImmutable' per' new DateTime() ' – Gyfis

+1

@Gyfis Strange, funziona bene per me. Ricorda che Immutables restituirà una nuova istanza una volta modificata. –

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