Commit 9415c792 by Carsten Brandt

date formatter fall back to PHP impl. to solve Y2K38 issue

formatting date and time values for years >=2038 or <=1901 is now possible also with intl extension is installed. 32bit systems will fall back to the PHP implementation because intl uses a 32bit UNIX timestamp internally. On a 64bit system the intl formatter is used in all cases if installed. fixes #5577
parent ea881351
...@@ -51,6 +51,10 @@ echo Yii::$app->formatter->asDate('2014-01-01'); // output: 1 января 2014 ...@@ -51,6 +51,10 @@ echo Yii::$app->formatter->asDate('2014-01-01'); // output: 1 января 2014
> [PHP intl extension](http://php.net/manual/en/book.intl.php) is installed or not. So to ensure your website works with the same output > [PHP intl extension](http://php.net/manual/en/book.intl.php) is installed or not. So to ensure your website works with the same output
> in all environments it is recommended to install the PHP intl extension in all environments and verify that the version of the ICU library > in all environments it is recommended to install the PHP intl extension in all environments and verify that the version of the ICU library
> is the same. See also: [Setting up your PHP environment for internationalization](tutorial-i18n.md#setup-environment). > is the same. See also: [Setting up your PHP environment for internationalization](tutorial-i18n.md#setup-environment).
>
> Note also that even if the intl extension is installed, formatting date and time values for years >=2038 or <=1901
> on 32bit systems will fall back to the PHP implementation, which does not provide localized month and day names,
> because intl uses a 32bit UNIX timestamp internally. On a 64bit system the intl formatter is used in all cases if installed.
Configuring the formatter <a name="configuring-format"></a> Configuring the formatter <a name="configuring-format"></a>
......
...@@ -4,6 +4,7 @@ Yii Framework 2 Change Log ...@@ -4,6 +4,7 @@ Yii Framework 2 Change Log
2.0.2 under development 2.0.2 under development
----------------------- -----------------------
- Bug #5577: formatting date and time values for years >=2038 or <=1901 on 32bit systems will not use intl extension but fall back to the PHP implementation (cebe)
- Bug #6080: Oracle DB schema did not load column types correctly (wenbin1989) - Bug #6080: Oracle DB schema did not load column types correctly (wenbin1989)
- Bug #6404: advanced application template `Alert` widget was generating duplicate IDs in case of multiple flashes (SDKiller) - Bug #6404: advanced application template `Alert` widget was generating duplicate IDs in case of multiple flashes (SDKiller)
- Bug #6557: Link URLs generated by `yii\widgets\Menu` are not encoded (qiangxue) - Bug #6557: Link URLs generated by `yii\widgets\Menu` are not encoded (qiangxue)
......
...@@ -35,6 +35,9 @@ use yii\helpers\Html; ...@@ -35,6 +35,9 @@ use yii\helpers\Html;
* the [PHP intl extension](http://php.net/manual/en/book.intl.php) has to be installed. * the [PHP intl extension](http://php.net/manual/en/book.intl.php) has to be installed.
* Most of the methods however work also if the PHP intl extension is not installed by providing * Most of the methods however work also if the PHP intl extension is not installed by providing
* a fallback implementation. Without intl month and day names are in English only. * a fallback implementation. Without intl month and day names are in English only.
* Note that even if the intl extension is installed, formatting date and time values for years >=2038 or <=1901
* on 32bit systems will fall back to the PHP implementation because intl uses a 32bit UNIX timestamp internally.
* On a 64bit system the intl formatter is used in all cases if installed.
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @author Enrica Ruedin <e.ruedin@guggach.com> * @author Enrica Ruedin <e.ruedin@guggach.com>
...@@ -543,7 +546,9 @@ class Formatter extends Component ...@@ -543,7 +546,9 @@ class Formatter extends Component
return $this->nullDisplay; return $this->nullDisplay;
} }
if ($this->_intlLoaded) { // intl does not work with dates >=2038 or <=1901 on 32bit machines, fall back to PHP
$year = $timestamp->format('Y');
if ($this->_intlLoaded && !(PHP_INT_SIZE == 4 && ($year <= 1901 || $year >= 2038))) {
if (strncmp($format, 'php:', 4) === 0) { if (strncmp($format, 'php:', 4) === 0) {
$format = FormatConverter::convertDatePhpToIcu(substr($format, 4)); $format = FormatConverter::convertDatePhpToIcu(substr($format, 4));
} }
......
...@@ -182,9 +182,7 @@ class FormatterDateTest extends TestCase ...@@ -182,9 +182,7 @@ class FormatterDateTest extends TestCase
public function testIntlDateRangeLow() public function testIntlDateRangeLow()
{ {
if (PHP_INT_SIZE == 4) { // 32bit systems // intl does not support high date ranges on 32bit systems, the implementation uses a fallback to PHP formatter
$this->markTestSkipped('intl does not support high date ranges on 32bit systems.');
}
$this->testDateRangeLow(); $this->testDateRangeLow();
} }
...@@ -196,13 +194,12 @@ class FormatterDateTest extends TestCase ...@@ -196,13 +194,12 @@ class FormatterDateTest extends TestCase
{ {
$this->assertSame('12-08-1922', $this->formatter->asDate('1922-08-12', 'dd-MM-yyyy')); $this->assertSame('12-08-1922', $this->formatter->asDate('1922-08-12', 'dd-MM-yyyy'));
$this->assertSame('14-01-1732', $this->formatter->asDate('1732-01-14', 'dd-MM-yyyy')); $this->assertSame('14-01-1732', $this->formatter->asDate('1732-01-14', 'dd-MM-yyyy'));
$this->assertSame('01-01-0000', $this->formatter->asDate('0000-01-01', 'dd-MM-yyyy'));
} }
public function testIntlDateRangeHigh() public function testIntlDateRangeHigh()
{ {
if (PHP_INT_SIZE == 4) { // 32bit systems // intl does not support high date ranges on 32bit systems, the implementation uses a fallback to PHP formatter
$this->markTestSkipped('intl does not support high date ranges on 32bit systems.');
}
$this->testDateRangeHigh(); $this->testDateRangeHigh();
} }
...@@ -214,6 +211,7 @@ class FormatterDateTest extends TestCase ...@@ -214,6 +211,7 @@ class FormatterDateTest extends TestCase
{ {
$this->assertSame('17-12-2048', $this->formatter->asDate('2048-12-17', 'dd-MM-yyyy')); $this->assertSame('17-12-2048', $this->formatter->asDate('2048-12-17', 'dd-MM-yyyy'));
$this->assertSame('17-12-3048', $this->formatter->asDate('3048-12-17', 'dd-MM-yyyy')); $this->assertSame('17-12-3048', $this->formatter->asDate('3048-12-17', 'dd-MM-yyyy'));
$this->assertSame('31-12-9999', $this->formatter->asDate('9999-12-31', 'dd-MM-yyyy'));
} }
private function buildDateSubIntervals($referenceDate, $intervals) private function buildDateSubIntervals($referenceDate, $intervals)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment