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 admite el constructor de DateTime.

Sinopsis de la Clase

class DateInterval {
/* Propiedades */
public integer $y;
public integer $m;
public integer $d;
public integer $h;
public integer $i;
public integer $s;
public mixed $days;
/* Métodos */
public __construct(string $interval_spec)
public format(string $format): string
}

Propiedades

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.

invert

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

days

Si el objeto DateInterval se creó con DateTime::diff(), entonces es el número total de días entre las fechas de inicio y fin. Si no, days será false.

Antes de PHP 5.4.20/5.5.4, en lugar de false se recibía -99999 al acceder a la propiedad.

Tabla de contenidos

add a note

User Contributed Notes 4 notes

up
45
cb
2 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
3
edgaras at levinson dot lt
6 months 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
1 year 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
anonymous at nospam dot com
17 days 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