Jelajahi Sumber

merged branch eriksencosta/issue-3841 (PR #4601)

Commits
-------

a609d55 [Locale] fixed StubIntlDateFormatter to behave like the ext/intl implementation

Discussion
----------

[2.0][WIP][Locale] StubIntlDateFormatter should use the TZ environment variable instead of the PHP's date.timezone setting

Bug fix: yes
Feature addition: no
Backwards compatibility break: yes
Symfony2 tests pass: yes
Fixes the following tickets: #3841
Todo: Check ext/intl changes for the next PHP 5.4 release
License of the code: MIT

![Build Status](https://secure.travis-ci.org/eriksencosta/symfony.png?branch=issue-3841)

There were changes that need to be investigated for the next PHP 5.4 release:

 - [php-src @ eb346ef](https://github.com/php/php-src/commit/eb346ef0f419b90739aadfb6cc7b7436c5b521d9)
 - [php-src @ 888e77f](https://github.com/php/php-src/commit/888e77ff733c5cb7c8f3d1fce6244463dd75a9b8)

A strong evidence of bug in ext/intl was found while testing `StubIntlDateFormatter`. See the comment available at the docblock of `StubIntlDateFormatterTest`'s `testFormatWithDefaultTimezoneIntlShouldUseTheTzEnvironmentVariableWhenAvailable()` method and the following Gist for test scripts: https://gist.github.com/2946342

Maybe the upcoming PHP 5.4 release fix this bug since it will use the PHP's `date.timezone` when no time zone is provided. If confirmed the bug, it will need to be reported to the ext/intl maintainers.

---------------------------------------------------------------------------

by travisbot at 2012-06-18T05:02:05Z

This pull request [passes](http://travis-ci.org/symfony/symfony/builds/1644431) (merged a609d55c into cd0aa378).

---------------------------------------------------------------------------

by fabpot at 2012-06-28T14:09:08Z

@eriksencosta Now that PHP 5.4.4 is out, our tests for the Locale components are broken. Is this PR ready to be merged?

---------------------------------------------------------------------------

by eriksencosta at 2012-06-28T14:53:14Z

@fabpot the failed test case seems unrelated to this issue. I will debug it.

Failed test: `Locale\Tests\Stub\StubNumberFormatterTest::testParseTypeInt64IntlWith32BitIntegerInPhp32Bit`

Recent build job: http://travis-ci.org/#!/symfony/symfony/jobs/1729618

I just need to confirm mine todo note. If you want, merge it, I'll track this and make a new PR if needed (possibly only to remove the TODO note.)
Fabien Potencier 13 tahun lalu
induk
melakukan
9572e9bd6e

+ 6 - 1
src/Symfony/Component/Locale/Stub/StubIntlDateFormatter.php

@@ -458,7 +458,12 @@ class StubIntlDateFormatter
     public function setTimeZoneId($timeZoneId)
     {
         if (null === $timeZoneId) {
-            $timeZoneId = date_default_timezone_get();
+            // TODO: changes were made to ext/intl in PHP 5.4.4 release that need to be investigated since it will
+            // use ini's date.timezone when the time zone is not provided. As a not well tested workaround, uses UTC.
+            // See the first two items of the commit message for more information:
+            // https://github.com/php/php-src/commit/eb346ef0f419b90739aadfb6cc7b7436c5b521d9
+            $timeZoneId = getenv('TZ') ?: 'UTC';
+
             $this->unitializedTimeZoneId = true;
         }
 

+ 53 - 2
tests/Symfony/Tests/Component/Locale/Stub/StubIntlDateFormatterTest.php

@@ -463,13 +463,62 @@ class StubIntlDateFormatterTest extends LocaleTestCase
     {
         $this->skipIfIntlExtensionIsNotLoaded();
         $this->skipIfICUVersionIsTooOld();
+
+        $formatter = new \IntlDateFormatter('en', StubIntlDateFormatter::MEDIUM, StubIntlDateFormatter::SHORT);
+        $formatter->setPattern('yyyy-MM-dd HH:mm:ss');
+
+        $this->assertEquals(
+            $this->createDateTime(0)->format('Y-m-d H:i:s'),
+            $formatter->format(0)
+        );
+    }
+
+    public function testFormatWithDefaultTimezoneStubShouldUseTheTzEnvironmentVariableWhenAvailable()
+    {
+        $tz = getenv('TZ');
+        putenv('TZ=Europe/London');
+
+        $formatter = new StubIntlDateFormatter('en', StubIntlDateFormatter::MEDIUM, StubIntlDateFormatter::SHORT);
+        $formatter->setPattern('yyyy-MM-dd HH:mm:ss');
+
+        $this->assertEquals(
+            $this->createDateTime(0)->format('Y-m-d H:i:s'),
+            $formatter->format(0)
+        );
+
+        $this->assertEquals('Europe/London', getenv('TZ'));
+
+        // Restores TZ.
+        putenv('TZ='.$tz);
+    }
+
+    /**
+     * It seems IntlDateFormatter caches the timezone id when not explicitely set via constructor or by the
+     * setTimeZoneId() method. Since testFormatWithDefaultTimezoneIntl() runs using the default environment
+     * time zone, this test would use it too if not running in a separated process.
+     *
+     * @runInSeparateProcess
+     */
+    public function testFormatWithDefaultTimezoneIntlShouldUseTheTzEnvironmentVariableWhenAvailable()
+    {
+        $this->skipIfIntlExtensionIsNotLoaded();
+        $this->skipIfICUVersionIsTooOld();
+
+        $tz = getenv('TZ');
+        putenv('TZ=Europe/Paris');
+
         $formatter = new \IntlDateFormatter('en', StubIntlDateFormatter::MEDIUM, StubIntlDateFormatter::SHORT);
         $formatter->setPattern('yyyy-MM-dd HH:mm:ss');
 
+        $this->assertEquals('Europe/Paris', getenv('TZ'));
+
         $this->assertEquals(
             $this->createDateTime(0)->format('Y-m-d H:i:s'),
             $formatter->format(0)
         );
+
+        // Restores TZ.
+        putenv('TZ='.$tz);
     }
 
     /**
@@ -994,11 +1043,13 @@ class StubIntlDateFormatterTest extends LocaleTestCase
         return new \IntlDateFormatter('en', \IntlDateFormatter::MEDIUM, \IntlDateFormatter::SHORT, 'UTC', \IntlDateFormatter::GREGORIAN, $pattern);
     }
 
-    protected function createDateTime($timestamp = null, $timeZone = null)
+    protected function createDateTime($timestamp = null)
     {
+        $timeZone = getenv('TZ') ?: 'UTC';
+
         $dateTime = new \DateTime();
         $dateTime->setTimestamp(null === $timestamp ? time() : $timestamp);
-        $dateTime->setTimeZone(new \DateTimeZone(null === $timeZone ? date_default_timezone_get() : $timeZone));
+        $dateTime->setTimeZone(new \DateTimeZone($timeZone));
 
         return $dateTime;
     }