Signature
date_interval_format(DateInterval $object, string $format): stringPurpose
date_interval_format() is the procedural alias of DateInterval::format(). It takes a DateInterval object and a format string, and returns a string in which each recognized token is replaced by a value from the interval. You use it to show a duration to a person: "2 days 3 hours", "+30 days", or a clock-like 04:05:06.
The function describes an interval; it does not do date arithmetic. It reads the stored fields (years, months, days, hours, minutes, seconds, microseconds, sign) and prints them as they are.
Signature
The object-oriented equivalent is $interval->format($format). Both behave identically.
Parameters
$object: theDateIntervalto print. It can come fromnew DateInterval('P1D')or fromdate_diff(). It has no default.$format: the template string. It has no default. Any text that is not a token is copied unchanged.
Every token starts with a percent sign. The ones you will use most:
%y/%Y: years, plain or padded to at least 2 digits%m/%M: months, plain or padded to 2 digits%d/%D: days, plain or padded to 2 digits%h/%H: hours, plain or padded to 2 digits%i/%I: minutes, plain or padded to 2 digits%s/%S: seconds, plain or padded to 2 digits%f/%F: microseconds, plain or padded to 6 digits%a: total number of days, only when the interval came from a date difference; otherwise the text(unknown)%R: sign, always+or-%r: sign,-when negative and empty when positive%%: a literal percent sign
Return value and failure cases
The function always returns a string. Passing something that is not a DateInterval as the first argument, or a value that cannot be used as a string for $format, raises a TypeError. Unknown tokens do not raise an error: the percent sign and the following character are left in the output as written.
Example 1: plain and padded tokens
Lowercase tokens print the raw number, while uppercase tokens pad it. Padding is handy for clock-like output.
$interval = new DateInterval('P1Y2M3DT4H5M6S');
echo date_interval_format($interval, '%y-%m-%d %h:%i:%s'), "\n";
echo date_interval_format($interval, '%Y-%M-%D %H:%I:%S'), "\n";1-2-3 4:5:6 01-02-03 04:05:06
Example 2: total days and the sign
When an interval is produced by date_diff(), %a holds the total number of days between the two dates. %R shows whether the second date lies before the first.
date_default_timezone_set('UTC');
$start = new DateTimeImmutable('2024-01-31');
$end = new DateTimeImmutable('2024-03-01');
echo date_interval_format(date_diff($start, $end), '%R%a days'), "\n";
echo date_interval_format(date_diff($end, $start), '%R%a days'), "\n";+30 days -30 days
Example 3: no normalization, literal percent, unknown total
An interval built from a specification keeps exactly the numbers you gave it. PT90S is 90 seconds, not 1 minute 30 seconds, and %a is unknown because no two dates were compared.
$interval = new DateInterval('PT90S');
$parts = [
date_interval_format($interval, '%i:%s'),
date_interval_format($interval, '%s%%'),
date_interval_format($interval, '%a'),
];
echo json_encode($parts, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";["0:90","90%","(unknown)"]
Edge cases
- No carrying over. The function never converts 90 seconds into minutes, or 25 hours into a day. If you need that, build the interval from a real date difference or normalize the values yourself.
%ais not always a number. Only intervals created by a date difference carry a total day count. For a constructed interval, the result is the string(unknown).- Sign handling. The numeric fields of a
DateIntervalare stored as non-negative numbers, and a separate invert flag records direction.%Ralways prints a sign, while%rprints one only for negative intervals. Choose%rwhen you want "-5" for negatives and "5" for positives. - Month and day parts of a diff. For a date difference, the
%mand%dparts depend on the calendar dates involved. Use%awhen you want an exact number of days. - Unknown tokens. A sequence like
%zis not replaced and stays in the output, which can look like a bug in a template.
Common mistakes
- Using date() tokens. Tokens like
%Yhere mean years in the interval, not a calendar year. Formats such asY-m-dwithout percent signs are copied literally. - Forgetting the percent sign.
dprints the letter d, while%dprints the days. - Expecting
%aon a manual interval. It prints(unknown). Compare two dates withdate_diff()if you need total days. - Confusing
%Rand%r.%Ryields+for positive intervals, which may be unwanted in user-facing text. - Mixing up
%Mand%I. UppercaseMis months and uppercaseIis minutes. Using%Mfor minutes is a frequent error. - Escaping a literal percent sign. To print
%, write%%.
Related functions
DateInterval::format(): the method this function aliasesdate_diff(): creates an interval between two datesdate_interval_create_from_date_string(): builds an interval from text like3 daysdate_add()anddate_sub(): apply an interval to a datedate_format(): formats a date rather than an interval
Recap
date_interval_format() takes a DateInterval and a template and returns a string. Lowercase tokens print raw values, uppercase tokens pad them, %R and %r show the sign, %a gives total days only for date differences, and %% prints a percent sign. Nothing is normalized, so what you stored is what you print.
Tested examples
$interval = new DateInterval('P1Y2M3DT4H5M6S');
echo date_interval_format($interval, '%y-%m-%d %h:%i:%s'), "\n";
echo date_interval_format($interval, '%Y-%M-%D %H:%I:%S'), "\n";
1-2-3 4:5:6 01-02-03 04:05:06
date_default_timezone_set('UTC');
$start = new DateTimeImmutable('2024-01-31');
$end = new DateTimeImmutable('2024-03-01');
echo date_interval_format(date_diff($start, $end), '%R%a days'), "\n";
echo date_interval_format(date_diff($end, $start), '%R%a days'), "\n";
+30 days -30 days
$interval = new DateInterval('PT90S');
$parts = [
date_interval_format($interval, '%i:%s'),
date_interval_format($interval, '%s%%'),
date_interval_format($interval, '%a'),
];
echo json_encode($parts, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
["0:90","90%","(unknown)"]