date_diff

Returns the difference between two date objects as a DateInterval of years, months, days and time.

Signature
date_diff(DateTimeInterface $baseObject, DateTimeInterface $targetObject, bool $absolute = false): DateInterval
  • Added in PHP 5.3.0

Parameters

ParameterTypeDescription
$baseObjectDateTimeInterfaceThe starting date, the one the interval is measured from.
$targetObjectDateTimeInterfaceThe date being compared to, the one the interval is measured to.
$absoluteoptionalbool= falseForce the interval to be reported as positive. It only clears the invert property; the component values are unsigned either way.

Return value

DateIntervalA DateInterval describing the time to add to baseObject to reach targetObject. The days property holds the total whole days; invert is 1 when targetObject is earlier than baseObject.

Errors

Throws a TypeError if either argument is not a DateTimeInterface instance.

date_diff is the procedural alias of DateTimeInterface::diff(). It takes two date objects and returns a DateInterval broken into years, months, days, hours, minutes and seconds, plus a days property holding the total number of whole days.

When to reach for it

Use it whenever the answer should be phrased the way a person would say it: "1 year, 5 months and 3 days", an age in whole years, a subscription's remaining term. Subtracting two timestamps gives you seconds, which you then have to divide by 86400 and hope no daylight saving transition sat in between. date_diff does the calendar work for you and is DST-aware, so a day that is 23 or 25 hours long still counts as one day.

Reading the result

The component properties are unsigned. Direction lives in invert, which is 1 when the target is earlier than the base. Set absolute to true when you only care about magnitude, and use %R in DateInterval::format() to print the sign.

d is the leftover days after whole years and months; days is the grand total. Mixing them up is the usual source of surprising numbers.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Calculating a person's age in whole years from a date of birth
  • Showing how many days remain before a subscription or trial expires
  • Reporting the elapsed time between an order being placed and shipped as days and hours

Frequently asked questions

How do I get the number of days between two dates in PHP?

Call date_diff and read the days property of the returned DateInterval, or format it with %a. Do not use the d property — that is the remainder after whole years and months.

What is the difference between date_diff and subtracting two timestamps?

Timestamp subtraction gives raw seconds and ignores the calendar, so daylight saving transitions and varying month lengths distort the result. date_diff returns calendar-correct years, months and days.

Why is my date_diff result negative or inverted?

Because the target date is earlier than the base date, which sets invert to 1. Pass true as the third argument, or swap the arguments, if you only want the magnitude.

More examples

Age in whole years

The y property already accounts for whether the birthday has happened this year, so no month-and-day comparison is needed. Passing absolute as true guarantees a positive result even if the arguments are swapped.

Example · php
<?php
date_default_timezone_set('UTC');

$born  = new DateTimeImmutable('1990-11-20');
$today = new DateTimeImmutable('2025-07-04');

$age = date_diff($born, $today, true);

echo 'age: ', $age->y, " years\n";
echo 'and ', $age->m, ' months, ', $age->d, " days\n";
echo 'lived ', $age->days, " days in total\n";

The absolute flag and the invert property

b is earlier than a, so the signed interval has invert set to 1 and %R prints a minus. The absolute flag only clears invert — the numeric properties were never negative to begin with.

Example · php
<?php
date_default_timezone_set('UTC');

$a = new DateTimeImmutable('2025-01-10');
$b = new DateTimeImmutable('2025-01-01');

$signed   = date_diff($a, $b);
$absolute = date_diff($a, $b, true);

echo 'signed  invert=', $signed->invert,   ' -> ', $signed->format('%R%a days'), "\n";
echo 'absolute invert=', $absolute->invert, ' -> ', $absolute->format('%R%a days'), "\n";
echo 'days property is unsigned either way: ', $signed->days, ' / ', $absolute->days, "\n";

Crossing a daylight saving change

Clocks jumped forward on the night of 30 March, so only 82800 seconds elapsed, but date_diff still reports one calendar day. Timestamp subtraction alone would have given 23 hours.

Example · php
<?php
$tz = new DateTimeZone('Europe/Berlin');

$before = new DateTimeImmutable('2025-03-29 12:00:00', $tz);
$after  = new DateTimeImmutable('2025-03-30 12:00:00', $tz);

$diff = date_diff($before, $after);

echo $diff->format("%a days, %h hours\n");
echo 'raw seconds apart: ', $after->getTimestamp() - $before->getTimestamp(), "\n";

Discussion

  • Be the first to comment on this lesson.