hora - Cómo podemos agregar dos intervalos de fechas en PHP
insertar calendario en formulario html (3)
Quiero agregar dos intervalos de fechas para calcular la duración total en horas y minutos. De hecho, deseo realizar una adición como se muestra a continuación:
$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;
Cualquier idea sobre cómo realizar este tipo de adición de intervalo para obtener la suma de los dos intervalos en formato de horas y minutos totales en PHP
Esta función le permite combinar cualquier cantidad 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);
}
PHP no tiene sobrecarga de operador * así que +
con objetos hace que PHP intente convertirlos a cadena primero, pero DateInterval
no admite eso:
interval 1: 03:05
interval 2: 05:00
Total interval : 08:05
En su lugar, debe crear un nuevo objeto DateTime
, luego usar la función de agregar para agregar los intervalos y finalmente mostrar la diferencia al 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";
Full 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 considerar buscar cómo DateInterval
almacena sus ''valores y luego extenderlos para hacer su propio cálculo. El siguiente ejemplo ( Demo ) es áspero, no tiene en cuenta la cosa invertida , no (re) establece $days
en false
y no he verificado / probado la especificación ISO del especificador de período en la creación, 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 PHP, en realidad es posible (al menos tipo de).
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>";