[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:
Jakub Zalas 2017-05-03 18:59:05 +01:00
parent 00acb37205
commit 5d3d1b25e0
No known key found for this signature in database
GPG Key ID: 15614199651BDE8D
5 changed files with 155 additions and 20 deletions

View File

@ -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(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::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
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::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', '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'),
@ -85,6 +87,9 @@ class DateTimeToLocalizedStringTransformerTest extends DateTimeTestCase
*/
public function testTransform($dateFormat, $timeFormat, $pattern, $output, $input)
{
IntlTestHelper::requireFullIntl($this, '59.1');
\Locale::setDefault('de_AT');
$transformer = new DateTimeToLocalizedStringTransformer(
'UTC',
'UTC',
@ -101,9 +106,12 @@ class DateTimeToLocalizedStringTransformerTest extends DateTimeTestCase
public function testTransformFullTime()
{
IntlTestHelper::requireFullIntl($this, '59.1');
\Locale::setDefault('de_AT');
$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()

View File

@ -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.');
}
// From ICU >= 4.8, the zero offset is not more used, example: GMT instead of GMT+00:00
$format = (0 !== (int) $dateTime->format('O')) ? '\G\M\TP' : '\G\M\T';
if ('Etc' === $timeZone) {
// 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);
}
/**

View File

@ -15,5 +15,7 @@ Resources
* [Report issues](https://github.com/symfony/symfony/issues) and
[send Pull Requests](https://github.com/symfony/symfony/pulls)
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

View File

@ -231,15 +231,8 @@ abstract class AbstractIntlDateFormatterTest extends TestCase
array('s', 43200, '0'), // 12 hours
// general
array("yyyy.MM.dd 'at' HH:mm:ss zzz", 0, '1970.01.01 at 00:00:00 GMT'),
array('K:mm a, z', 0, '0:00 AM, GMT'),
// timezone
array('z', 0, 'GMT'),
array('zz', 0, 'GMT'),
array('zzz', 0, 'GMT'),
array('zzzz', 0, 'GMT'),
array('zzzzz', 0, '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, UTC'),
);
$dateTime = new \DateTime('@0');
@ -250,12 +243,25 @@ abstract class AbstractIntlDateFormatterTest extends TestCase
$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("yyyy.MM.dd 'at' HH:mm:ss zzz", $dateTime, '1970.01.01 at 00:00:00 GMT');
$formatData[] = array('K:mm a, z', $dateTime, '0:00 AM, 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, UTC');
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
*/
@ -334,6 +340,75 @@ abstract class AbstractIntlDateFormatterTest extends TestCase
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()
{
$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'))) {
$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));
}
@ -482,8 +560,8 @@ abstract class AbstractIntlDateFormatterTest extends TestCase
array(0, IntlDateFormatter::LONG, IntlDateFormatter::NONE, 'January 1, 1970'),
array(0, IntlDateFormatter::MEDIUM, IntlDateFormatter::NONE, 'Jan 1, 1970'),
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::LONG, '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 UTC'),
array(0, IntlDateFormatter::NONE, IntlDateFormatter::MEDIUM, '12:00:00 AM'),
array(0, IntlDateFormatter::NONE, IntlDateFormatter::SHORT, '12:00 AM'),
);

View File

@ -43,6 +43,34 @@ class IntlDateFormatterTest extends AbstractIntlDateFormatterTest
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)
{
IntlTestHelper::requireFullIntl($this, '55.1');