Skip to content
PHP News
Search
Voting PHP 8.7

IntlRelativeDateTimeFormatter: "3 Days Ago" in Any Locale

On the PHP wiki as IntlRelativeDateTimeFormatter

Adds IntlRelativeDateTimeFormatter for localized strings like "3 days ago" and "next Sunday".

Add IntlRelativeDateTimeFormatter as described to ext/intl?

Primary vote · 2/3 majority

13 Yes 0 No 100% approval

Closes .

Voting closes on October 22, 2026. The primary poll currently has 8 Yes votes, 0 No votes and 0 Abstain votes. It needs a two-thirds majority to pass.

Summary

Apps show strings like "3 days ago", "in 2 weeks", "yesterday" and "next Sunday" all the time. PHP has no built-in way to produce them in every language. Developers often write their own plural rules, unit names and word order. Weilin Du announced the RFC on internals to add an IntlRelativeDateTimeFormatter class to the intl extension, using ICU's existing relative date formatter.

How it works

You create a formatter for a locale, then pass it a number and a unit:

$formatter = new IntlRelativeDateTimeFormatter('en_US');

echo $formatter->format(-1, IntlRelativeDateTimeFormatterUnit::Day);
// yesterday

echo $formatter->format(2, IntlRelativeDateTimeFormatterUnit::Week);
// in 2 weeks

echo $formatter->formatNumeric(-1, IntlRelativeDateTimeFormatterUnit::Day);
// 1 day ago

Negative numbers mean the past and positive numbers mean the future. format() uses words like "yesterday" when the locale has them. formatNumeric() always uses a number. The formatter accepts weekday units, too, so you can request phrases such as "last Sunday".

The RFC also adds three pure enums for styles, capitalization contexts and units. An optional NumberFormatter controls numeric output. combineDateAndTime() joins a relative date and a time. Error accessors match other intl classes. The API does not accept a date or timestamp, and it does not choose the unit for you. Your code still decides between "in 7 days" and "in 1 week".

What it means for existing code

The change adds one class and three enums in the global namespace. Existing intl behavior does not change, but userland classes with those names could clash when intl is loaded. The implementation is under review.