[Intl][Form] Update tests, TimeZoneTransformer, and DateTimeToLocalizedStringTransformer for the GMT and UTC split in ICU
The [GMT timezone has been split from the UTC](http://site.icu-project.org/download/59) timezone [in CLDR](http://cldr.unicode.org/index/downloads/cldr-31) (which ICU is based on). For example, the code blow: * before ICU 59.1 would return "GMT" in all cases * with ICU 59.1 it returns "UTC" for the first three ('z', 'zz', 'zzz') and "Coordinated Universal Time" for the last two ('zzzz', 'zzzzz'). ```php foreach (['z', 'zz', 'zzz', 'zzzz', 'zzzzz'] as $pattern) { $formatter = new \IntlDateFormatter('en', IntlDateFormatter::MEDIUM, IntlDateFormatter::SHORT, new \DateTimeZone('UTC'), IntlDateFormatter::GREGORIAN, $pattern); var_dump($formatter->format(new \DateTime('@0'))); } ``` Similarly Form's `DateTimeToLocalizedStringTransformer` is also affected: ```php $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', null, \IntlDateFormatter::FULL); var_dump($transformer->transform(new \DateTime('2010-02-03 04:05:06 UTC'))); // ICU 58.2: '03.02.2010, 04:05:06 GMT' // ICU 59.1: '03.02.2010, 04:05:06 Koordinierte Weltzeit' ``` Refer to added and modified test cases for more changes. I split this PR in two commits for easier review. First commit updates ICU data (generated files), the second updates code and test cases to be compatible with updated data.
This commit is contained in:
parent
00acb37205
commit
5d3d1b25e0
@ -61,11 +61,13 @@ class DateTimeToLocalizedStringTransformerTest extends DateTimeTestCase
|
|||||||
array(\IntlDateFormatter::FULL, \IntlDateFormatter::NONE, null, 'Mittwoch, 3. Februar 2010', '2010-02-03 00:00:00 UTC'),
|
array(\IntlDateFormatter::FULL, \IntlDateFormatter::NONE, null, 'Mittwoch, 3. Februar 2010', '2010-02-03 00:00:00 UTC'),
|
||||||
array(null, \IntlDateFormatter::SHORT, null, '03.02.2010, 04:05', '2010-02-03 04:05:00 UTC'),
|
array(null, \IntlDateFormatter::SHORT, null, '03.02.2010, 04:05', '2010-02-03 04:05:00 UTC'),
|
||||||
array(null, \IntlDateFormatter::MEDIUM, null, '03.02.2010, 04:05:06', '2010-02-03 04:05:06 UTC'),
|
array(null, \IntlDateFormatter::MEDIUM, null, '03.02.2010, 04:05:06', '2010-02-03 04:05:06 UTC'),
|
||||||
array(null, \IntlDateFormatter::LONG, null, '03.02.2010, 04:05:06 GMT', '2010-02-03 04:05:06 UTC'),
|
array(null, \IntlDateFormatter::LONG, null, '03.02.2010, 04:05:06 UTC', '2010-02-03 04:05:06 UTC'),
|
||||||
|
array(null, \IntlDateFormatter::LONG, null, '03.02.2010, 04:05:06 UTC', '2010-02-03 04:05:06 GMT'),
|
||||||
// see below for extra test case for time format FULL
|
// see below for extra test case for time format FULL
|
||||||
array(\IntlDateFormatter::NONE, \IntlDateFormatter::SHORT, null, '04:05', '1970-01-01 04:05:00 UTC'),
|
array(\IntlDateFormatter::NONE, \IntlDateFormatter::SHORT, null, '04:05', '1970-01-01 04:05:00 UTC'),
|
||||||
array(\IntlDateFormatter::NONE, \IntlDateFormatter::MEDIUM, null, '04:05:06', '1970-01-01 04:05:06 UTC'),
|
array(\IntlDateFormatter::NONE, \IntlDateFormatter::MEDIUM, null, '04:05:06', '1970-01-01 04:05:06 UTC'),
|
||||||
array(\IntlDateFormatter::NONE, \IntlDateFormatter::LONG, null, '04:05:06 GMT', '1970-01-01 04:05:06 UTC'),
|
array(\IntlDateFormatter::NONE, \IntlDateFormatter::LONG, null, '04:05:06 UTC', '1970-01-01 04:05:06 GMT'),
|
||||||
|
array(\IntlDateFormatter::NONE, \IntlDateFormatter::LONG, null, '04:05:06 UTC', '1970-01-01 04:05:06 UTC'),
|
||||||
array(null, null, 'yyyy-MM-dd HH:mm:00', '2010-02-03 04:05:00', '2010-02-03 04:05:00 UTC'),
|
array(null, null, 'yyyy-MM-dd HH:mm:00', '2010-02-03 04:05:00', '2010-02-03 04:05:00 UTC'),
|
||||||
array(null, null, 'yyyy-MM-dd HH:mm', '2010-02-03 04:05', '2010-02-03 04:05:00 UTC'),
|
array(null, null, 'yyyy-MM-dd HH:mm', '2010-02-03 04:05', '2010-02-03 04:05:00 UTC'),
|
||||||
array(null, null, 'yyyy-MM-dd HH', '2010-02-03 04', '2010-02-03 04:00:00 UTC'),
|
array(null, null, 'yyyy-MM-dd HH', '2010-02-03 04', '2010-02-03 04:00:00 UTC'),
|
||||||
@ -85,6 +87,9 @@ class DateTimeToLocalizedStringTransformerTest extends DateTimeTestCase
|
|||||||
*/
|
*/
|
||||||
public function testTransform($dateFormat, $timeFormat, $pattern, $output, $input)
|
public function testTransform($dateFormat, $timeFormat, $pattern, $output, $input)
|
||||||
{
|
{
|
||||||
|
IntlTestHelper::requireFullIntl($this, '59.1');
|
||||||
|
\Locale::setDefault('de_AT');
|
||||||
|
|
||||||
$transformer = new DateTimeToLocalizedStringTransformer(
|
$transformer = new DateTimeToLocalizedStringTransformer(
|
||||||
'UTC',
|
'UTC',
|
||||||
'UTC',
|
'UTC',
|
||||||
@ -101,9 +106,12 @@ class DateTimeToLocalizedStringTransformerTest extends DateTimeTestCase
|
|||||||
|
|
||||||
public function testTransformFullTime()
|
public function testTransformFullTime()
|
||||||
{
|
{
|
||||||
|
IntlTestHelper::requireFullIntl($this, '59.1');
|
||||||
|
\Locale::setDefault('de_AT');
|
||||||
|
|
||||||
$transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', null, \IntlDateFormatter::FULL);
|
$transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', null, \IntlDateFormatter::FULL);
|
||||||
|
|
||||||
$this->assertEquals('03.02.2010, 04:05:06 GMT', $transformer->transform($this->dateTime));
|
$this->assertEquals('03.02.2010, 04:05:06 Koordinierte Weltzeit', $transformer->transform($this->dateTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testTransformToDifferentLocale()
|
public function testTransformToDifferentLocale()
|
||||||
|
@ -33,10 +33,29 @@ class TimeZoneTransformer extends Transformer
|
|||||||
throw new NotImplementedException('Time zone different than GMT or UTC is not supported as a formatting output.');
|
throw new NotImplementedException('Time zone different than GMT or UTC is not supported as a formatting output.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// From ICU >= 4.8, the zero offset is not more used, example: GMT instead of GMT+00:00
|
if ('Etc' === $timeZone) {
|
||||||
$format = (0 !== (int) $dateTime->format('O')) ? '\G\M\TP' : '\G\M\T';
|
// i.e. Etc/GMT+1, Etc/UTC, Etc/Zulu
|
||||||
|
$timeZone = substr($dateTime->getTimezone()->getName(), 4);
|
||||||
|
}
|
||||||
|
|
||||||
return $dateTime->format($format);
|
// From ICU >= 59.1 GMT and UTC are no longer unified
|
||||||
|
if (in_array($timeZone, array('UTC', 'UCT', 'Universal', 'Zulu'))) {
|
||||||
|
// offset is not supported with UTC
|
||||||
|
return $length > 3 ? 'Coordinated Universal Time' : 'UTC';
|
||||||
|
}
|
||||||
|
|
||||||
|
$offset = (int) $dateTime->format('O');
|
||||||
|
|
||||||
|
// From ICU >= 4.8, the zero offset is no more used, example: GMT instead of GMT+00:00
|
||||||
|
if (0 === $offset) {
|
||||||
|
return $length > 3 ? 'Greenwich Mean Time' : 'GMT';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($length > 3) {
|
||||||
|
return $dateTime->format('\G\M\TP');
|
||||||
|
}
|
||||||
|
|
||||||
|
return sprintf('GMT%s%d', ($offset >= 0 ? '+' : ''), $offset / 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,5 +15,7 @@ Resources
|
|||||||
* [Report issues](https://github.com/symfony/symfony/issues) and
|
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||||
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||||
in the [main Symfony repository](https://github.com/symfony/symfony)
|
in the [main Symfony repository](https://github.com/symfony/symfony)
|
||||||
|
* [Docker images with intl support](https://hub.docker.com/r/jakzal/php-intl)
|
||||||
|
(for the Intl component development)
|
||||||
|
|
||||||
[0]: http://www.php.net/manual/en/intl.setup.php
|
[0]: http://www.php.net/manual/en/intl.setup.php
|
||||||
|
@ -231,15 +231,8 @@ abstract class AbstractIntlDateFormatterTest extends TestCase
|
|||||||
array('s', 43200, '0'), // 12 hours
|
array('s', 43200, '0'), // 12 hours
|
||||||
|
|
||||||
// general
|
// general
|
||||||
array("yyyy.MM.dd 'at' HH:mm:ss zzz", 0, '1970.01.01 at 00:00:00 GMT'),
|
array("yyyy.MM.dd 'at' HH:mm:ss zzz", 0, '1970.01.01 at 00:00:00 UTC'),
|
||||||
array('K:mm a, z', 0, '0:00 AM, GMT'),
|
array('K:mm a, z', 0, '0:00 AM, UTC'),
|
||||||
|
|
||||||
// timezone
|
|
||||||
array('z', 0, 'GMT'),
|
|
||||||
array('zz', 0, 'GMT'),
|
|
||||||
array('zzz', 0, 'GMT'),
|
|
||||||
array('zzzz', 0, 'GMT'),
|
|
||||||
array('zzzzz', 0, 'GMT'),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
$dateTime = new \DateTime('@0');
|
$dateTime = new \DateTime('@0');
|
||||||
@ -250,12 +243,25 @@ abstract class AbstractIntlDateFormatterTest extends TestCase
|
|||||||
$formatData[] = array('h:mm a', $dateTime, '12:00 AM');
|
$formatData[] = array('h:mm a', $dateTime, '12:00 AM');
|
||||||
$formatData[] = array('yyyyy.MMMM.dd hh:mm aaa', $dateTime, '01970.January.01 12:00 AM');
|
$formatData[] = array('yyyyy.MMMM.dd hh:mm aaa', $dateTime, '01970.January.01 12:00 AM');
|
||||||
|
|
||||||
$formatData[] = array("yyyy.MM.dd 'at' HH:mm:ss zzz", $dateTime, '1970.01.01 at 00:00:00 GMT');
|
$formatData[] = array("yyyy.MM.dd 'at' HH:mm:ss zzz", $dateTime, '1970.01.01 at 00:00:00 UTC');
|
||||||
$formatData[] = array('K:mm a, z', $dateTime, '0:00 AM, GMT');
|
$formatData[] = array('K:mm a, z', $dateTime, '0:00 AM, UTC');
|
||||||
|
|
||||||
return $formatData;
|
return $formatData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @requires PHP 5.5.10
|
||||||
|
*/
|
||||||
|
public function testFormatUtcAndGmtAreSplit()
|
||||||
|
{
|
||||||
|
$pattern = "yyyy.MM.dd 'at' HH:mm:ss zzz";
|
||||||
|
$gmtFormatter = $this->getDateFormatter('en', IntlDateFormatter::MEDIUM, IntlDateFormatter::SHORT, 'GMT', IntlDateFormatter::GREGORIAN, $pattern);
|
||||||
|
$utcFormatter = $this->getDateFormatter('en', IntlDateFormatter::MEDIUM, IntlDateFormatter::SHORT, 'UTC', IntlDateFormatter::GREGORIAN, $pattern);
|
||||||
|
|
||||||
|
$this->assertSame('1970.01.01 at 00:00:00 GMT', $gmtFormatter->format(new \DateTime('@0')));
|
||||||
|
$this->assertSame('1970.01.01 at 00:00:00 UTC', $utcFormatter->format(new \DateTime('@0')));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider formatErrorProvider
|
* @dataProvider formatErrorProvider
|
||||||
*/
|
*/
|
||||||
@ -334,6 +340,75 @@ abstract class AbstractIntlDateFormatterTest extends TestCase
|
|||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider formatTimezoneProvider
|
||||||
|
* @requires PHP 5.5
|
||||||
|
*/
|
||||||
|
public function testFormatTimezone($pattern, $timezone, $expected)
|
||||||
|
{
|
||||||
|
$formatter = $this->getDefaultDateFormatter($pattern);
|
||||||
|
$formatter->setTimeZone(new \DateTimeZone($timezone));
|
||||||
|
|
||||||
|
$this->assertEquals($expected, $formatter->format(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function formatTimezoneProvider()
|
||||||
|
{
|
||||||
|
$cases = array(
|
||||||
|
array('z', 'GMT', 'GMT'),
|
||||||
|
array('zz', 'GMT', 'GMT'),
|
||||||
|
array('zzz', 'GMT', 'GMT'),
|
||||||
|
array('zzzz', 'GMT', 'Greenwich Mean Time'),
|
||||||
|
array('zzzzz', 'GMT', 'Greenwich Mean Time'),
|
||||||
|
|
||||||
|
array('z', 'Etc/GMT', 'GMT'),
|
||||||
|
array('zz', 'Etc/GMT', 'GMT'),
|
||||||
|
array('zzz', 'Etc/GMT', 'GMT'),
|
||||||
|
array('zzzz', 'Etc/GMT', 'Greenwich Mean Time'),
|
||||||
|
array('zzzzz', 'Etc/GMT', 'Greenwich Mean Time'),
|
||||||
|
|
||||||
|
array('z', 'Etc/GMT+3', 'GMT-3'),
|
||||||
|
array('zz', 'Etc/GMT+3', 'GMT-3'),
|
||||||
|
array('zzz', 'Etc/GMT+3', 'GMT-3'),
|
||||||
|
array('zzzz', 'Etc/GMT+3', 'GMT-03:00'),
|
||||||
|
array('zzzzz', 'Etc/GMT+3', 'GMT-03:00'),
|
||||||
|
|
||||||
|
array('z', 'UTC', 'UTC'),
|
||||||
|
array('zz', 'UTC', 'UTC'),
|
||||||
|
array('zzz', 'UTC', 'UTC'),
|
||||||
|
array('zzzz', 'UTC', 'Coordinated Universal Time'),
|
||||||
|
array('zzzzz', 'UTC', 'Coordinated Universal Time'),
|
||||||
|
|
||||||
|
array('z', 'Etc/UTC', 'UTC'),
|
||||||
|
array('zz', 'Etc/UTC', 'UTC'),
|
||||||
|
array('zzz', 'Etc/UTC', 'UTC'),
|
||||||
|
array('zzzz', 'Etc/UTC', 'Coordinated Universal Time'),
|
||||||
|
array('zzzzz', 'Etc/UTC', 'Coordinated Universal Time'),
|
||||||
|
|
||||||
|
array('z', 'Etc/Universal', 'UTC'),
|
||||||
|
array('z', 'Etc/Zulu', 'UTC'),
|
||||||
|
array('z', 'Etc/UCT', 'UTC'),
|
||||||
|
array('z', 'Etc/Greenwich', 'GMT'),
|
||||||
|
array('zzzzz', 'Etc/Universal', 'Coordinated Universal Time'),
|
||||||
|
array('zzzzz', 'Etc/Zulu', 'Coordinated Universal Time'),
|
||||||
|
array('zzzzz', 'Etc/UCT', 'Coordinated Universal Time'),
|
||||||
|
array('zzzzz', 'Etc/Greenwich', 'Greenwich Mean Time'),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!defined('HHVM_VERSION')) {
|
||||||
|
// these timezones are not considered valid in HHVM
|
||||||
|
$cases = array_merge($cases, array(
|
||||||
|
array('z', 'GMT+03:00', 'GMT+3'),
|
||||||
|
array('zz', 'GMT+03:00', 'GMT+3'),
|
||||||
|
array('zzz', 'GMT+03:00', 'GMT+3'),
|
||||||
|
array('zzzz', 'GMT+03:00', 'GMT+03:00'),
|
||||||
|
array('zzzzz', 'GMT+03:00', 'GMT+03:00'),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $cases;
|
||||||
|
}
|
||||||
|
|
||||||
public function testFormatWithGmtTimezone()
|
public function testFormatWithGmtTimezone()
|
||||||
{
|
{
|
||||||
$formatter = $this->getDefaultDateFormatter('zzzz');
|
$formatter = $this->getDefaultDateFormatter('zzzz');
|
||||||
@ -389,8 +464,11 @@ abstract class AbstractIntlDateFormatterTest extends TestCase
|
|||||||
if (PHP_VERSION_ID < 50500 && !(extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) {
|
if (PHP_VERSION_ID < 50500 && !(extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) {
|
||||||
$this->markTestSkipped('Only in PHP 5.5+ IntlDateFormatter allows to use DateTimeZone objects.');
|
$this->markTestSkipped('Only in PHP 5.5+ IntlDateFormatter allows to use DateTimeZone objects.');
|
||||||
}
|
}
|
||||||
|
if (PHP_VERSION_ID < 50510) {
|
||||||
|
$this->markTestSkipped('Before PHP 5.5.10 the GMT timezone used to be converted to UTC.');
|
||||||
|
}
|
||||||
|
|
||||||
$formatter = $this->getDateFormatter('en', IntlDateFormatter::MEDIUM, IntlDateFormatter::SHORT, new \DateTimeZone('GMT'), IntlDateFormatter::GREGORIAN, 'zzzz');
|
$formatter = $this->getDateFormatter('en', IntlDateFormatter::MEDIUM, IntlDateFormatter::SHORT, new \DateTimeZone('GMT'), IntlDateFormatter::GREGORIAN, 'zzz');
|
||||||
|
|
||||||
$this->assertEquals('GMT', $formatter->format(0));
|
$this->assertEquals('GMT', $formatter->format(0));
|
||||||
}
|
}
|
||||||
@ -482,8 +560,8 @@ abstract class AbstractIntlDateFormatterTest extends TestCase
|
|||||||
array(0, IntlDateFormatter::LONG, IntlDateFormatter::NONE, 'January 1, 1970'),
|
array(0, IntlDateFormatter::LONG, IntlDateFormatter::NONE, 'January 1, 1970'),
|
||||||
array(0, IntlDateFormatter::MEDIUM, IntlDateFormatter::NONE, 'Jan 1, 1970'),
|
array(0, IntlDateFormatter::MEDIUM, IntlDateFormatter::NONE, 'Jan 1, 1970'),
|
||||||
array(0, IntlDateFormatter::SHORT, IntlDateFormatter::NONE, '1/1/70'),
|
array(0, IntlDateFormatter::SHORT, IntlDateFormatter::NONE, '1/1/70'),
|
||||||
array(0, IntlDateFormatter::NONE, IntlDateFormatter::FULL, '12:00:00 AM GMT'),
|
array(0, IntlDateFormatter::NONE, IntlDateFormatter::FULL, '12:00:00 AM Coordinated Universal Time'),
|
||||||
array(0, IntlDateFormatter::NONE, IntlDateFormatter::LONG, '12:00:00 AM GMT'),
|
array(0, IntlDateFormatter::NONE, IntlDateFormatter::LONG, '12:00:00 AM UTC'),
|
||||||
array(0, IntlDateFormatter::NONE, IntlDateFormatter::MEDIUM, '12:00:00 AM'),
|
array(0, IntlDateFormatter::NONE, IntlDateFormatter::MEDIUM, '12:00:00 AM'),
|
||||||
array(0, IntlDateFormatter::NONE, IntlDateFormatter::SHORT, '12:00 AM'),
|
array(0, IntlDateFormatter::NONE, IntlDateFormatter::SHORT, '12:00 AM'),
|
||||||
);
|
);
|
||||||
|
@ -43,6 +43,34 @@ class IntlDateFormatterTest extends AbstractIntlDateFormatterTest
|
|||||||
parent::testFormatWithTimezoneFromEnvironmentVariable();
|
parent::testFormatWithTimezoneFromEnvironmentVariable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider formatTimezoneProvider
|
||||||
|
* @requires PHP 5.5
|
||||||
|
*/
|
||||||
|
public function testFormatTimezone($pattern, $timezone, $expected)
|
||||||
|
{
|
||||||
|
IntlTestHelper::requireFullIntl($this, '59.1');
|
||||||
|
|
||||||
|
parent::testFormatTimezone($pattern, $timezone, $expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFormatUtcAndGmtAreSplit()
|
||||||
|
{
|
||||||
|
IntlTestHelper::requireFullIntl($this, '59.1');
|
||||||
|
|
||||||
|
parent::testFormatUtcAndGmtAreSplit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider dateAndTimeTypeProvider
|
||||||
|
*/
|
||||||
|
public function testDateAndTimeType($timestamp, $datetype, $timetype, $expected)
|
||||||
|
{
|
||||||
|
IntlTestHelper::requireFullIntl($this, '59.1');
|
||||||
|
|
||||||
|
parent::testDateAndTimeType($timestamp, $datetype, $timetype, $expected);
|
||||||
|
}
|
||||||
|
|
||||||
protected function getDateFormatter($locale, $datetype, $timetype, $timezone = null, $calendar = IntlDateFormatter::GREGORIAN, $pattern = null)
|
protected function getDateFormatter($locale, $datetype, $timetype, $timezone = null, $calendar = IntlDateFormatter::GREGORIAN, $pattern = null)
|
||||||
{
|
{
|
||||||
IntlTestHelper::requireFullIntl($this, '55.1');
|
IntlTestHelper::requireFullIntl($this, '55.1');
|
||||||
|
Reference in New Issue
Block a user