Browse Source

added support for non-gregorian calendar to formatter

fixes #8687
close #10517
tags/2.0.7
Carsten Brandt 9 years ago
parent
commit
cdb7d84fea
  1. 3
      docs/guide/output-formatting.md
  2. 1
      framework/CHANGELOG.md
  3. 39
      framework/i18n/Formatter.php
  4. 37
      tests/framework/i18n/FormatterDateTest.php

3
docs/guide/output-formatting.md

@ -107,6 +107,9 @@ The following format shortcuts are supported (the examples assume `en_GB` is the
- `long`: will output `6 October 2014` and `15:58:42 GMT`;
- `full`: will output `Monday, 6 October 2014` and `15:58:42 GMT`.
Since version 2.0.7 it is also possible to format dates in different calendar systems.
Please refer to the API documentation of the formatters [[yii\i18n\Formatter::$calendar|$calendar]]-property on how to set a different calendar.
### Time Zones <span id="time-zones"></span>

1
framework/CHANGELOG.md

@ -61,6 +61,7 @@ Yii Framework 2 Change Log
- Enh #8329: Added support of options for `message` console command (vchenin)
- Enh #8613: `yii\widgets\FragmentCache` will not store empty content anymore which fixes some problems related to `yii\filters\PageCache` (kidol)
- Enh #8649: Added total applied migrations to final report (vernik91)
- Enh #8687: Added support for non-gregorian calendars, e.g. persian, taiwan, islamic to `yii\i18n\Formatter` (cebe, z-avanes, hooman-pro)
- Enh #8995: `yii\validators\FileValidator::maxFiles` can be set to `0` to allow unlimited count of files (PowerGamer1, silverfire)
- Enh #9282: Improved JSON error handling to support PHP 5.5 error codes (freezy-sk)
- Enh #9337: Added `yii\db\ColumnSchemaBuilder::defaultExpression()` to support DB Expression as default value (kotchuprik)

39
framework/i18n/Formatter.php

@ -139,6 +139,37 @@ class Formatter extends Component
*/
public $datetimeFormat = 'medium';
/**
* @var \IntlCalendar|int|null the calendar to be used for date formatting. The value of this property will be directly
* passed to the [constructor of the `IntlDateFormatter` class](http://php.net/manual/en/intldateformatter.create.php).
*
* Defaults to `null`, which means the Gregorian calendar will be used. You may also explicitly pass the constant
* `\IntlDateFormatter::GREGORIAN` for Gregorian calendar.
*
* To use an alternative calendar like for example the [Jalali calendar](https://en.wikipedia.org/wiki/Jalali_calendar),
* set this property to `\IntlDateFormatter::TRADITIONAL`.
* The calendar must then be specified in the [[locale]], for example for the persian calendar the configuration for the formatter would be:
*
* ```php
* 'formatter' => [
* 'locale' => 'fa_IR@calendar=persian',
* 'calendar' => \IntlDateFormatter::TRADITIONAL,
* ],
* ```
*
* Available calendar names can be found in the [ICU manual](http://userguide.icu-project.org/datetime/calendar).
*
* Since PHP 5.5 you may also use an instance of the [[\IntlCalendar]] class.
* Check the [PHP manual](http://php.net/manual/en/intldateformatter.create.php) for more details.
*
* If the [PHP intl extension](http://php.net/manual/en/book.intl.php) is not available, setting this property will have no effect.
*
* @see http://php.net/manual/en/intldateformatter.create.php
* @see http://php.net/manual/en/class.intldateformatter.php#intl.intldateformatter-constants.calendartypes
* @see http://php.net/manual/en/class.intlcalendar.php
* @since 2.0.7
*/
public $calendar;
/**
* @var string the character displayed as the decimal point when formatting a number.
* If not set, the decimal separator corresponding to [[locale]] will be used.
* If [PHP intl extension](http://php.net/manual/en/book.intl.php) is not available, the default value is '.'.
@ -574,14 +605,14 @@ class Formatter extends Component
}
if (isset($this->_dateFormats[$format])) {
if ($type === 'date') {
$formatter = new IntlDateFormatter($this->locale, $this->_dateFormats[$format], IntlDateFormatter::NONE, $timeZone);
$formatter = new IntlDateFormatter($this->locale, $this->_dateFormats[$format], IntlDateFormatter::NONE, $timeZone, $this->calendar);
} elseif ($type === 'time') {
$formatter = new IntlDateFormatter($this->locale, IntlDateFormatter::NONE, $this->_dateFormats[$format], $timeZone);
$formatter = new IntlDateFormatter($this->locale, IntlDateFormatter::NONE, $this->_dateFormats[$format], $timeZone, $this->calendar);
} else {
$formatter = new IntlDateFormatter($this->locale, $this->_dateFormats[$format], $this->_dateFormats[$format], $timeZone);
$formatter = new IntlDateFormatter($this->locale, $this->_dateFormats[$format], $this->_dateFormats[$format], $timeZone, $this->calendar);
}
} else {
$formatter = new IntlDateFormatter($this->locale, IntlDateFormatter::NONE, IntlDateFormatter::NONE, $timeZone, null, $format);
$formatter = new IntlDateFormatter($this->locale, IntlDateFormatter::NONE, IntlDateFormatter::NONE, $timeZone, $this->calendar, $format);
}
if ($formatter === null) {
throw new InvalidConfigException(intl_get_error_message());

37
tests/framework/i18n/FormatterDateTest.php

@ -88,6 +88,43 @@ class FormatterDateTest extends TestCase
$this->assertSame($this->formatter->nullDisplay, $this->formatter->asDate(null));
}
public function testIntlAsDateOtherCalendars()
{
// Persian calendar
$this->formatter->locale = 'fa_IR@calendar=persian';
$this->formatter->calendar = \IntlDateFormatter::TRADITIONAL;
$this->formatter->timeZone = 'UTC';
$value = 1451606400; // Fri, 01 Jan 2016 00:00:00 (UTC)
$this->assertSame('۱۳۹۴', $this->formatter->asDate($value, 'php:Y'));
$value = new DateTime();
$value->setTimestamp(1451606400); // Fri, 01 Jan 2016 00:00:00 (UTC)
$this->assertSame('۱۳۹۴', $this->formatter->asDate($value, 'php:Y'));
if (version_compare(PHP_VERSION, '5.5.0', '>=')) {
$value = new \DateTimeImmutable('2016-01-01 00:00:00', new \DateTimeZone('UTC'));
$this->assertSame('۱۳۹۴', $this->formatter->asDate($value, 'php:Y'));
}
// Buddhist calendar
$this->formatter->locale = 'fr_FR@calendar=buddhist';
$this->formatter->calendar = \IntlDateFormatter::TRADITIONAL;
$this->formatter->timeZone = 'UTC';
$value = 1451606400; // Fri, 01 Jan 2016 00:00:00 (UTC)
$this->assertSame('2559', $this->formatter->asDate($value, 'php:Y'));
$value = new DateTime();
$value->setTimestamp(1451606400); // Fri, 01 Jan 2016 00:00:00 (UTC)
$this->assertSame('2559', $this->formatter->asDate($value, 'php:Y'));
if (version_compare(PHP_VERSION, '5.5.0', '>=')) {
$value = new \DateTimeImmutable('2016-01-01 00:00:00', new \DateTimeZone('UTC'));
$this->assertSame('2559', $this->formatter->asDate($value, 'php:Y'));
}
}
public function testIntlAsTime()
{
$this->testAsTime();

Loading…
Cancel
Save