La clase DateInterval

(PHP 5 >= 5.3.0, PHP 7, PHP 8)

Introducción

Representa un intervalo de fechas.

Un intervalo de fechas almacena o bien una cantidad fija de instantes (en años, meses, días, horas, etc.) o bien una cadena con un instante relativo en el formato que admiten los constructores de DateTimeImmutable y DateTime.

Más especificamente, la información en un objeto de la clase DateInterval es una instrucción para llegar de un instante de fecha/hora a otro instante de fecha/hora. Este proceso no es siempre reversible.

Un modo común de crear un objeto DateInterval es calculando la diferencia entre dos objetos de fecha/hora a través de DateTimeInterface::diff().

Dado que no hay una forma bien definida de comparar intervalos de fechas, las instancias de DateInterval son incomparables.

Sinopsis de la Clase

class DateInterval {
/* Propiedades */
public int $y;
public int $m;
public int $d;
public int $h;
public int $i;
public int $s;
public float $f;
public int $invert;
public mixed $days;
/* Métodos */
public __construct(string $duration)
public static createFromDateString(string $datetime): DateInterval
public format(string $format): string
}

Propiedades

Advertencia

El listado de propiedades disponibles que se muestra a continuación depende de la versión de PHP, y deben considerarse como de solo lectura.

y

Número de años.

m

Número de meses.

d

Número de días.

h

Número de horas.

i

Número de minutos.

s

Número de segundos.

f

Número de microsegundos, como fracción de un segundo.

invert

Es 1 si el intervalo representa un periodo de tiempo negativo y 0 en caso contrario. Véase DateInterval::format().

days

If the DateInterval object was created by DateTimeImmutable::diff() or DateTime::diff(), then this is the total number of full days between the start and end dates. Otherwise, days will be false.

from_string

Si el objeto DateInterval fue creado por DateInterval::createFromDateString(), entonces esta propiedad tendrá el valor true, y será establecida la propiedad date_string. De lo contrario, el valor será false, y serán establecidas las propiedades y a f, invert, y days.

date_string

La cadena usada como argumento en DateInterval::createFromDateString().

Historial de cambios

Versión Descripción
8.2.0 Se han añadido las propiedades from_string y date_string para las instancias de DateInterval que fueron creadas usando el método DateInterval::createFromDateString().
8.2.0 Solo las propiedades y a f, invert, y days serán visibles.
7.4.0 Ahora las instancias de DateInterval son incomparables; anteriormente, todas las instancias de DateInterval se consideraban iguales.
7.1.0 Se ha añadido la propiedad f.

Tabla de contenidos

add a note

User Contributed Notes 5 notes

up
56
cb
3 years ago
If you want to reverse a date interval use array_reverse and iterator_to_array. I've found using invert to be unreliable.

<?php
$start_date = date_create("2021-01-01");
$end_date   = date_create("2021-01-05"); // If you want to include this date, add 1 day

$interval = DateInterval::createFromDateString('1 day');
$daterange = new DatePeriod($start_date, $interval ,$end_date);

function show_dates ($dr) {
    foreach($dr as $date1){
        echo $date1->format('Y-m-d').'<br>';
    }
}
 
show_dates ($daterange);
   
echo '<br>';

// reverse the array

$daterange = array_reverse(iterator_to_array($daterange));

show_dates ($daterange);
           
?>

Gives 
 2021-01-01
 2021-01-02
 2021-01-03
 2021-01-04

 2021-01-04
 2021-01-03
 2021-01-02
 2021-01-01
up
4
edgaras at levinson dot lt
1 year ago
There is a handy way to compare intervals by adding them to 0 dates and comparing dates instead

<?php

function compare(DateInterval $first, DateInterval $second): int
{
    $firstDate = (new DateTime())->setTimestamp(0)->add($first);
    $secondDate = (new DateTime())->setTimestamp(0)->add($second);

    return $firstDate <=> $secondDate;
}

echo compare(new DateInterval('P2D'), new DateInterval('PT48H')) . PHP_EOL;
echo compare(DateInterval::createFromDateString('2 days'), DateInterval::createFromDateString('48 hours')) . PHP_EOL;
echo compare(DateInterval::createFromDateString('2 days'), DateInterval::createFromDateString('49 hours')) . PHP_EOL;
echo compare(DateInterval::createFromDateString('2 days'), DateInterval::createFromDateString('47 hours')) . PHP_EOL;

?>

Outputs:
0
0
-1
1
up
2
julio dot necronomicon at gmail dot com
2 years ago
More simple example i use to add or subtract.

<?php
$Datetime = new Datetime('NOW', new DateTimeZone('America/Bahia'));
$Datetime->add(DateInterval::createFromDateString('2 day'));

echo $Datetime->format("Y-m-d H:i:s");
?>
up
0
eof at tty3 dot dev
10 hours ago
I typically ignore the comments section on php.net; however, I should note that it is wrong to even attempt comparison between date intervals by adding them to a zero date because PHP's date intervals are stored in ambiguous units of time (days, months, and years are not regular).

a correct date interval is stored in terms of seconds (plus integer microseconds, typically) between the two dates. any more coarse measurement for approximate purposes is then derived from the interval. 

just skip this entirely, and write your own interval type based on the above, from first principals. it's easy.
up
0
anonymous at nospam dot com
11 months ago
Subtracting months may not work as you might expect. 
Code shows how subtracting 2 months from consecutive days produces potentially unexpected results. 

<?php
$origin = date_create('2025-01-31T00:00:00');
$target = date_create('2024-11-26T00:00:00');

$interval = date_diff($origin, $target);
echo "interval total days: ".$interval->format('%a days');

echo "interval object years: ".$interval->format('%y years');
echo "interval object months: ".$interval->format('%m months');
echo "interval object days: ".$interval->format('%d days');

// create 3 dates that are consecutive, but in two months
$d1 = date_create('2025-01-31T00:00:00');
$d2 = date_create('2025-02-01T00:00:00');
$d3 = date_create('2025-02-02T00:00:00');

// add (negative) interval object to each date
$d1->add($interval);
$d2->add($interval);
$d3->add($interval);

echo "Add (negative) interval object to each date. Non-consecutive results: ";
echo($d1->format("Y-m-d\TH:i:s"));
echo($d2->format("Y-m-d\TH:i:s"));
echo($d3->format("Y-m-d\TH:i:s"));

// reset dates
$d1 = date_create('2025-01-31T00:00:00');
$d2 = date_create('2025-02-01T00:00:00');
$d3 = date_create('2025-02-02T00:00:00');

// Use same dates, but subtract total number of days instead of adding interval object: ";
$d1->sub(new DateInterval('P'.$interval->format('%a').'D'));
$d2->sub(new DateInterval('P'.$interval->format('%a').'D'));
$d3->sub(new DateInterval('P'.$interval->format('%a').'D'));

echo "Use same dates, but subtract total number of days instead of adding interval object. Results (consecutive): ";
echo($d1->format("Y-m-d\TH:i:s"));
echo($d2->format("Y-m-d\TH:i:s"));
echo($d3->format("Y-m-d\TH:i:s"));

$d1 = date_create('2025-01-31T00:00:00');
$d2 = date_create('2025-02-01T00:00:00');
$d3 = date_create('2025-02-02T00:00:00');

// do month separately for 2025-02-01T00:00:00
echo "Do month separately (interesting): ";

echo ('Subtract '. $interval->format('%m').' months (might not expect this):');
echo ('Jan 31 - 2 months (61 days = Dec, 31 days + Nov, 30 days) ==> Dec 1');
echo ('Feb 1  - 2 months (62 days = Dec, 31 days + Jan, 31 days) ==> Dec 1');
$d1->sub(new DateInterval('P'.$interval->format('%m').'M'));
echo $d1->format("Y-m-d\TH:i:s");
$d2->sub(new DateInterval('P'.$interval->format('%m').'M'));
echo $d2->format("Y-m-d\TH:i:s");
$d3->sub(new DateInterval('P'.$interval->format('%m').'M'));
echo $d3->format("Y-m-d\TH:i:s");
?>

Output: 

interval total days: 66 days
interval object years: 0 years
interval object months: 2 months
interval object days: 5 days

create 3 dates that are consecutive, but in two months:
$d1 = 2025-01-31T00:00:00
$d2 = 2025-02-01T00:00:00
$d3 = 2025-02-02T00:00:00

Add (negative) interval object to each date. Non-consecutive results:
2024-11-26T00:00:00
2024-11-26T00:00:00
2024-11-27T00:00:00

Use same dates, but subtract total number of days instead of adding interval object. Results (consecutive):
2024-11-26T00:00:00
2024-11-27T00:00:00
2024-11-28T00:00:00

Do month separately (interesting):

Subtract 2 months (might not expect this):
Jan 31 - 2 months (61 days = Dec, 31 days + Nov, 30 days) ==> Dec 1
Feb 1 - 2 months (62 days = Dec, 31 days + Jan, 31 days) ==> Dec 1
2024-12-01T00:00:00
2024-12-01T00:00:00
2024-12-02T00:00:00
To Top