From 5776f76068dd2c56d302cde5bf4e726a1bb58e22 Mon Sep 17 00:00:00 2001 From: Quentin Schuler Date: Thu, 2 Feb 2023 09:24:56 +0100 Subject: [PATCH] Add the new PHP 8.0 IntlDateFormatter::RELATIVE_* constants for date formatting. --- doc/filters/format_datetime.rst | 6 +++ extra/intl-extra/IntlExtension.php | 45 ++++++++++++++++--- .../Tests/Fixtures/format_date_php8.test | 12 +++++ 3 files changed, 56 insertions(+), 7 deletions(-) create mode 100644 extra/intl-extra/Tests/Fixtures/format_date_php8.test diff --git a/doc/filters/format_datetime.rst b/doc/filters/format_datetime.rst index e5c07228a..8f3b46d47 100644 --- a/doc/filters/format_datetime.rst +++ b/doc/filters/format_datetime.rst @@ -26,6 +26,12 @@ You can tweak the output for the date part and the time part: Supported values are: ``none``, ``short``, ``medium``, ``long``, and ``full``. +.. versionadded:: 3.6 + + ``relative_short``, ``relative_medium``, ``relative_long``, and ``relative_full`` are also supported when running on + PHP 8.0 and superior or when using a polyfill that define the ``IntlDateFormatter::RELATIVE_*`` constants and + associated behavior. + For greater flexibility, you can even define your own pattern (see the `ICU user guide`_ for supported patterns). diff --git a/extra/intl-extra/IntlExtension.php b/extra/intl-extra/IntlExtension.php index 76c2b271e..955d6ec92 100644 --- a/extra/intl-extra/IntlExtension.php +++ b/extra/intl-extra/IntlExtension.php @@ -26,7 +26,36 @@ use Twig\TwigFunction; final class IntlExtension extends AbstractExtension { - private const DATE_FORMATS = [ + private static function availableDateFormats(): array + { + static $formats = null; + + if (null !== $formats) { + return $formats; + } + + $formats = [ + 'none' => \IntlDateFormatter::NONE, + 'short' => \IntlDateFormatter::SHORT, + 'medium' => \IntlDateFormatter::MEDIUM, + 'long' => \IntlDateFormatter::LONG, + 'full' => \IntlDateFormatter::FULL, + ]; + + // Assuming that each `RELATIVE_*` constant are defined when one of them is. + if (\defined('IntlDateFormatter::RELATIVE_FULL')) { + $formats = array_merge($formats, [ + 'relative_short' => \IntlDateFormatter::RELATIVE_SHORT, + 'relative_medium' => \IntlDateFormatter::RELATIVE_MEDIUM, + 'relative_long' => \IntlDateFormatter::RELATIVE_LONG, + 'relative_full' => \IntlDateFormatter::RELATIVE_FULL, + ]); + } + + return $formats; + } + + private const TIME_FORMATS = [ 'none' => \IntlDateFormatter::NONE, 'short' => \IntlDateFormatter::SHORT, 'medium' => \IntlDateFormatter::MEDIUM, @@ -370,12 +399,14 @@ final class IntlExtension extends AbstractExtension private function createDateFormatter(?string $locale, ?string $dateFormat, ?string $timeFormat, string $pattern, \DateTimeZone $timezone, string $calendar): \IntlDateFormatter { - if (null !== $dateFormat && !isset(self::DATE_FORMATS[$dateFormat])) { - throw new RuntimeError(sprintf('The date format "%s" does not exist, known formats are: "%s".', $dateFormat, implode('", "', array_keys(self::DATE_FORMATS)))); + $dateFormats = self::availableDateFormats(); + + if (null !== $dateFormat && !isset($dateFormats[$dateFormat])) { + throw new RuntimeError(sprintf('The date format "%s" does not exist, known formats are: "%s".', $dateFormat, implode('", "', array_keys($dateFormats)))); } - if (null !== $timeFormat && !isset(self::DATE_FORMATS[$timeFormat])) { - throw new RuntimeError(sprintf('The time format "%s" does not exist, known formats are: "%s".', $timeFormat, implode('", "', array_keys(self::DATE_FORMATS)))); + if (null !== $timeFormat && !isset(self::TIME_FORMATS[$timeFormat])) { + throw new RuntimeError(sprintf('The time format "%s" does not exist, known formats are: "%s".', $timeFormat, implode('", "', array_keys(self::TIME_FORMATS)))); } if (null === $locale) { @@ -384,8 +415,8 @@ final class IntlExtension extends AbstractExtension $calendar = 'gregorian' === $calendar ? \IntlDateFormatter::GREGORIAN : \IntlDateFormatter::TRADITIONAL; - $dateFormatValue = self::DATE_FORMATS[$dateFormat] ?? null; - $timeFormatValue = self::DATE_FORMATS[$timeFormat] ?? null; + $dateFormatValue = $dateFormats[$dateFormat] ?? null; + $timeFormatValue = self::TIME_FORMATS[$timeFormat] ?? null; if ($this->dateFormatterPrototype) { $dateFormatValue = $dateFormatValue ?: $this->dateFormatterPrototype->getDateType(); diff --git a/extra/intl-extra/Tests/Fixtures/format_date_php8.test b/extra/intl-extra/Tests/Fixtures/format_date_php8.test new file mode 100644 index 000000000..67e0e6f4d --- /dev/null +++ b/extra/intl-extra/Tests/Fixtures/format_date_php8.test @@ -0,0 +1,12 @@ +--TEST-- +"format_date" filter +--CONDITION-- +PHP_VERSION_ID >= 80000 +--TEMPLATE-- +{{ 'today 23:39:12'|format_datetime('relative_short', 'none', locale='fr') }} +{{ 'today 23:39:12'|format_datetime('relative_full', 'full', locale='fr') }} +--DATA-- +return []; +--EXPECT-- +aujourd’hui +aujourd’hui à 23:39:12 temps universel coordonné