Skip to content

IntlExtension >= 3.8 throws Exception when formatDateTime is used and $timezone === null #3965

@TPantelConventus

Description

@TPantelConventus

Background

The Exception occurred after I updated from 3.7 to 3.8 and the Workaround for me right now is to downgrade to 3.7.

Description

I use the fomat_datetime filter in many places in my app like this:

{{ presentation.presentationFileUploadedAt | format_datetime('medium', timezone=false, locale=app.request.locale) }}

Before the update of "twig/intl-extra" from 3.7 to 3.8 that worked without any problems, but when i updated to 3.8 it suddenly gave me Excpetions:

An exception has been thrown during the rendering of a template ("Twig\Extra\Intl\IntlExtension::createDateFormatter(): Argument #5 ($timezone) must be of type ?DateTimeZone, bool given, called in /var/www/html/vendor/twig/intl-extra/IntlExtension.php on line 379").

That was wondering me a lot, so I looked into IntlExtension.php to look for the corresponding line:

/**
     * @param \DateTimeInterface|string|null  $date     A date or null to use the current time
     * @param \DateTimeZone|string|false|null $timezone The target timezone, null to use the default, false to leave unchanged
     */
    public function formatDateTime(Environment $env, $date, ?string $dateFormat = 'medium', ?string $timeFormat = 'medium', string $pattern = '', $timezone = null, string $calendar = 'gregorian', string $locale = null): string
    {
        $date = twig_date_converter($env, $date, $timezone);

        $formatterTimezone = $timezone;
        if (null === $formatterTimezone) {
            $formatterTimezone = $date->getTimezone();
        } elseif (\is_string($formatterTimezone)) {
            $formatterTimezone = new \DateTimeZone($timezone);
        }
      // THE NEXT LINE IS LINE 379
  $formatter = $this->createDateFormatter($locale, $dateFormat, $timeFormat, $pattern, $formatterTimezone, $calendar); 

        if (false === $ret = $formatter->format($date)) {
            throw new RuntimeError('Unable to format the given date.');
        }

        return $ret;
    }

So formatDateTime (which the twig filter uses) accepts $timezone === false, but then in line 379 createDateFormatter() is called with $formatterTimezone being false, throwing the Exception, because:

private function createDateFormatter(?string $locale, ?string $dateFormat, ?string $timeFormat, string $pattern, ?\DateTimeZone $timezone, string $calendar): \IntlDateFormatter

The solution would be to modify the formatDateTimeFunction:

/**
     * @param \DateTimeInterface|string|null  $date     A date or null to use the current time
     * @param \DateTimeZone|string|false|null $timezone The target timezone, null to use the default, false to leave unchanged
     */
    public function formatDateTime(Environment $env, $date, ?string $dateFormat = 'medium', ?string $timeFormat = 'medium', string $pattern = '', $timezone = null, string $calendar = 'gregorian', string $locale = null): string
    {
        $date = twig_date_converter($env, $date, $timezone);

        $formatterTimezone = $timezone;
        if (null === $formatterTimezone || false === $formatterTimezone ) {
            $formatterTimezone = $date->getTimezone();
        } elseif (\is_string($formatterTimezone)) {
            $formatterTimezone = new \DateTimeZone($timezone);
        }
      // THE NEXT LINE IS LINE 379
  $formatter = $this->createDateFormatter($locale, $dateFormat, $timeFormat, $pattern, $formatterTimezone, $calendar); 

        if (false === $ret = $formatter->format($date)) {
            throw new RuntimeError('Unable to format the given date.');
        }

        return $ret;
    }

Replacing the twig filter from timezone=false to timezone=null is NOT a valid solution, as it prevents the Exception from being thrown, BUT results in a wrong time being displayed, because the $date variable in the function is depending on $timezone and not $formatterTimezone

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions