Skip to content

Commit 065634f

Browse files
committed
bug #3844 Fix IntlExtension::formatDateTime use of date formatter prototype (drjayvee)
This PR was squashed before being merged into the 3.x branch. Discussion ---------- Fix IntlExtension::formatDateTime use of date formatter prototype See twigphp/intl-extra#6 for more details Commits ------- c75762c Fix IntlExtension::formatDateTime use of date formatter prototype
2 parents 248855b + c75762c commit 065634f

2 files changed

Lines changed: 57 additions & 6 deletions

File tree

extra/intl-extra/IntlExtension.php

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,14 @@ public function formatNumberStyle(string $style, $number, array $attrs = [], str
369369
public function formatDateTime(Environment $env, $date, ?string $dateFormat = 'medium', ?string $timeFormat = 'medium', string $pattern = '', $timezone = null, string $calendar = 'gregorian', string $locale = null): string
370370
{
371371
$date = twig_date_converter($env, $date, $timezone);
372-
$formatter = $this->createDateFormatter($locale, $dateFormat, $timeFormat, $pattern, $date->getTimezone(), $calendar);
372+
373+
$formatterTimezone = $timezone;
374+
if (false === $formatterTimezone) {
375+
$formatterTimezone = $date->getTimezone();
376+
} elseif (\is_string($formatterTimezone)) {
377+
$formatterTimezone = new \DateTimeZone($timezone);
378+
}
379+
$formatter = $this->createDateFormatter($locale, $dateFormat, $timeFormat, $pattern, $formatterTimezone, $calendar);
373380

374381
if (false === $ret = $formatter->format($date)) {
375382
throw new RuntimeError('Unable to format the given date.');
@@ -396,7 +403,7 @@ public function formatTime(Environment $env, $date, ?string $timeFormat = 'mediu
396403
return $this->formatDateTime($env, $date, 'none', $timeFormat, $pattern, $timezone, $calendar, $locale);
397404
}
398405

399-
private function createDateFormatter(?string $locale, ?string $dateFormat, ?string $timeFormat, string $pattern, \DateTimeZone $timezone, string $calendar): \IntlDateFormatter
406+
private function createDateFormatter(?string $locale, ?string $dateFormat, ?string $timeFormat, string $pattern, ?\DateTimeZone $timezone, string $calendar): \IntlDateFormatter
400407
{
401408
$dateFormats = self::availableDateFormats();
402409

@@ -409,7 +416,10 @@ private function createDateFormatter(?string $locale, ?string $dateFormat, ?stri
409416
}
410417

411418
if (null === $locale) {
412-
$locale = \Locale::getDefault();
419+
if ($this->dateFormatterPrototype) {
420+
$locale = $this->dateFormatterPrototype->getLocale();
421+
}
422+
$locale = $locale ?: \Locale::getDefault();
413423
}
414424

415425
$calendar = 'gregorian' === $calendar ? \IntlDateFormatter::GREGORIAN : \IntlDateFormatter::TRADITIONAL;
@@ -420,12 +430,14 @@ private function createDateFormatter(?string $locale, ?string $dateFormat, ?stri
420430
if ($this->dateFormatterPrototype) {
421431
$dateFormatValue = $dateFormatValue ?: $this->dateFormatterPrototype->getDateType();
422432
$timeFormatValue = $timeFormatValue ?: $this->dateFormatterPrototype->getTimeType();
423-
$timezone = $timezone ?: $this->dateFormatterPrototype->getTimeType();
433+
$timezone = $timezone ?: $this->dateFormatterPrototype->getTimeZone()->toDateTimeZone();
424434
$calendar = $calendar ?: $this->dateFormatterPrototype->getCalendar();
425435
$pattern = $pattern ?: $this->dateFormatterPrototype->getPattern();
426436
}
427437

428-
$hash = $locale.'|'.$dateFormatValue.'|'.$timeFormatValue.'|'.$timezone->getName().'|'.$calendar.'|'.$pattern;
438+
$timezoneName = $timezone ? $timezone->getName() : '(none)';
439+
440+
$hash = $locale.'|'.$dateFormatValue.'|'.$timeFormatValue.'|'.$timezoneName.'|'.$calendar.'|'.$pattern;
429441

430442
if (!isset($this->dateFormatters[$hash])) {
431443
$this->dateFormatters[$hash] = new \IntlDateFormatter($locale, $dateFormatValue, $timeFormatValue, $timezone, $calendar, $pattern);

extra/intl-extra/Tests/IntlExtensionTest.php

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,56 @@
1212
namespace Twig\Extra\Intl\Tests;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Twig\Environment;
1516
use Twig\Extra\Intl\IntlExtension;
17+
use Twig\Loader\ArrayLoader;
1618

1719
class IntlExtensionTest extends TestCase
1820
{
21+
public function testFormatterWithoutProto()
22+
{
23+
$ext = new IntlExtension();
24+
$env = new Environment(new ArrayLoader());
25+
26+
$this->assertSame('12.346', $ext->formatNumber('12.3456'));
27+
$this->assertSame(
28+
'Feb 20, 2020, 1:37:00 PM',
29+
$ext->formatDateTime($env, new \DateTime('2020-02-20T13:37:00+00:00'))
30+
);
31+
}
32+
1933
public function testFormatterProto()
2034
{
21-
$dateFormatterProto = new \IntlDateFormatter('fr', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL);
35+
$dateFormatterProto = new \IntlDateFormatter('fr', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, new \DateTimeZone('Europe/Paris'));
2236
$numberFormatterProto = new \NumberFormatter('fr', \NumberFormatter::DECIMAL);
2337
$numberFormatterProto->setTextAttribute(\NumberFormatter::POSITIVE_PREFIX, '++');
2438
$numberFormatterProto->setAttribute(\NumberFormatter::FRACTION_DIGITS, 1);
2539
$ext = new IntlExtension($dateFormatterProto, $numberFormatterProto);
40+
$env = new Environment(new ArrayLoader());
41+
2642
$this->assertSame('++12,3', $ext->formatNumber('12.3456'));
43+
$this->assertSame(
44+
'jeudi 20 février 2020 à 14:37:00 heure normale d’Europe centrale',
45+
$ext->formatDateTime($env, new \DateTime('2020-02-20T13:37:00+00:00'))
46+
);
47+
}
48+
49+
public function testFormatterOverridenProto()
50+
{
51+
$dateFormatterProto = new \IntlDateFormatter('fr', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, new \DateTimeZone('Europe/Paris'));
52+
$numberFormatterProto = new \NumberFormatter('fr', \NumberFormatter::DECIMAL);
53+
$numberFormatterProto->setTextAttribute(\NumberFormatter::POSITIVE_PREFIX, '++');
54+
$numberFormatterProto->setAttribute(\NumberFormatter::FRACTION_DIGITS, 1);
55+
$ext = new IntlExtension($dateFormatterProto, $numberFormatterProto);
56+
$env = new Environment(new ArrayLoader());
57+
58+
$this->assertSame(
59+
'twelve point three',
60+
$ext->formatNumber('12.3456', [], 'spellout', 'default', 'en_US')
61+
);
62+
$this->assertSame(
63+
'2020-02-20 13:37:00',
64+
$ext->formatDateTime($env, new \DateTime('2020-02-20T13:37:00+00:00'), 'short', 'short', 'yyyy-MM-dd HH:mm:ss', 'UTC', 'gregorian', 'en_US')
65+
);
2766
}
2867
}

0 commit comments

Comments
 (0)