Форматирование данных
=====================

Для форматирования вывода Yii предоставляет класс, преобразующий данные в человеко-понятный формат.
[[yii\i18n\Formatter]] это класс-помощник, который зарегистрирован как
[компонент приложения](structure-application-components.md), по умолчанию под именем `formatter`.

Он предоставляет набор методов для форматирования таких данных как дата/время, числа и другие часто используемые в целях
локализации форматы.
Formatter может быть использован двумя различными способами.

1. Напрямую, используя методы форматирования (все методы форматирования имеют префикс `as`):

   ```php
   echo Yii::$app->formatter->asDate('2014-01-01', 'long'); // выведет: January 1, 2014
   echo Yii::$app->formatter->asPercent(0.125, 2); // выведет: 12.50%
   echo Yii::$app->formatter->asEmail('cebe@example.com'); // выведет: <a href="mailto:cebe@example.com">cebe@example.com</a>
   echo Yii::$app->formatter->asBoolean(true); // выведет: Yes
   // он также умеет отображать null значения:
   echo Yii::$app->formatter->asDate(null); // выведет: (not set)
   ```

2. Используя метод [[yii\i18n\Formatter::format()|format()]] и имя формата.
   Этот метод также используется в виджетах наподобие [[yii\grid\GridView]] и [[yii\widgets\DetailView]], в которых
   вы можете задать формат отображения данных в колонке через конфигурацию виджета.

   ```php
   echo Yii::$app->formatter->format('2014-01-01', 'date'); // выведет: January 1, 2014
   // вы также можете использовать массивы для настроек метода форматирования:
   // `2` это значение для $decimals параметра метода asPercent().
   echo Yii::$app->formatter->format(0.125, ['percent', 2]); // выведет: 12.50%
   ```

Все данные, отображаемые через компонент formatter, будут локализованы, если
[расширение PHP intl](https://www.php.net/manual/ru/book.intl.php) было установлено. Для этого вы можете настроить свойство
[[yii\i18n\Formatter::locale|locale]]. Если оно не было настроено, то в качестве локали будет использован
[[yii\base\Application::language|язык приложения]]. Подробнее смотрите в разделе «[интернационализация](tutorial-i18n.md)».
Компонент форматирования будет выбирать корректный формат для даты и чисел в соответствии с локалью, включая имена
месяцев и дней недели, переведённые на текущий язык.
Форматирование дат также зависит от [[yii\i18n\Formatter::timeZone|часового пояса]], который будет взят из одноимённого свойства [[yii\base\Application::timeZone|timeZone]] приложения, если не был задан явно. В свою очередь [[yii\base\Application::timeZone|timeZone]] устанавливает / читает временную зону PHP.

Например, форматирование даты, вызванное с разной локалью, отобразит разные результаты::

```php
Yii::$app->formatter->locale = 'en-US';
echo Yii::$app->formatter->asDate('2014-01-01'); // выведет: January 1, 2014
Yii::$app->formatter->locale = 'de-DE';
echo Yii::$app->formatter->asDate('2014-01-01'); // выведет: 1. January 2014
Yii::$app->formatter->locale = 'ru-RU';
echo Yii::$app->formatter->asDate('2014-01-01'); // выведет: 1 января 2014 г.
```

> Обратите внимание, что форматирование может различаться между различными версиями библиотеки ICU, собранных с PHP,
> а также на основе того установлено ли [расширение PHP intl](https://www.php.net/manual/ru/book.intl.php) или нет.
> Таким образом, чтобы гарантировать, что ваш сайт будет одинаково отображать данные во всех окружениях рекомендуется
> установить расширение PHP intl во всех окружениях и проверить, что версия библиотеки ICU совпадает.
> См. также: [Настройка PHP окружения для интернационализации](tutorial-i18n.md#setup-environment).
>
> Отметим также, что даже если установлено расширение PHP intl, форматирование даты и времени для значений года >=2038
> или <=1901 на 32-ух разрядных системах будет обращаться к реализации PHP, которая не обеспечивает локализованные
> имена месяца и дня, потому что в этом случае intl будет использовать 32-ух битный UNIX timestamp. На 64-битной системе
> intl formatter будет работать во всех случаях, если, конечно, intl был установлен.


Настройка форматирования <span id="configuring-format"></span>
--------------------------------------------------------------

Форматы по умолчанию, используемые в методах форматирования, можно настраивать через свойства
[[yii\i18n\Formatter|класса форматирования]]. Вы можете задать форматирование по умолчанию для всего приложения, настроив
компонент `formatter` в вашей [конфигурации приложения](concept-configurations.md#application-configurations). Ниже
приведён пример конфигурации. Чтобы узнать больше о доступных свойствах см. [[yii\i18n\Formatter|API документацию к классу Formatter]]
и следующие подсекции.

```php
'components' => [
    'formatter' => [
        'dateFormat' => 'dd.MM.yyyy',
        'decimalSeparator' => ',',
        'thousandSeparator' => ' ',
        'currencyCode' => 'EUR',
   ],
],
```

Форматирование значений даты и времени <span id="date-and-time"></span>
-----------------------------------------------------------------------

Класс форматирования предоставляет различные методы для форматирования значений даты и времени. Например:

- [[yii\i18n\Formatter::asDate()|date]] — значение будет отформатировано как дата, например `January 01, 2014`.
- [[yii\i18n\Formatter::asTime()|time]] — значение будет отформатировано как время, например `14:23`.
- [[yii\i18n\Formatter::asDatetime()|datetime]] — значение будет отформатировано как дата и время, например
  `January 01, 2014 14:23`.
- [[yii\i18n\Formatter::asTimestamp()|timestamp]] — значение будет отформатировано как
  [unix timestamp](https://ru.wikipedia.org/wiki/UNIX-время), например, `1412609982`.
- [[yii\i18n\Formatter::asRelativeTime()|relativeTime]] — значение будет отформатировано как временной промежуток между
  заданной датой и текущим временем в человеко понятном формате, например: `1 час назад`.
- [[yii\i18n\Formatter::asDuration()|duration]]: значение будет отформатировано как продолжительность в человеко-понятном
  формате, например `1 день, 2 минуты`.

Форматирование даты и времени для методов [[yii\i18n\Formatter::asDate()|date]], [[yii\i18n\Formatter::asTime()|time]] и 
[[yii\i18n\Formatter::asDatetime()|datetime]] может быть задано глобально через конфигурацию свойств форматирования
[[yii\i18n\Formatter::$dateFormat|$dateFormat]], [[yii\i18n\Formatter::$timeFormat|$timeFormat]] и
[[yii\i18n\Formatter::$datetimeFormat|$datetimeFormat]].

По умолчанию, форматирование использует сокращенный формат, который интерпретируется по-разному в зависимости от активной
в данный момент локали. Поэтому дата и время будут отформатированы наиболее часто используемым способом в стране и языке
пользователя. Доступны 4 разных сокращенных формата:

- `short` в локали `en_GB` отобразит, например, `06/10/2014` для даты и `15:58` для времени, в то время как
- `medium` будет отображать `6 Oct 2014` и `15:58:42` соответственно,
- `long` будет отображать `6 October 2014` и `15:58:42 GMT` соответственно и
- `full` будет отображать `Monday, 6 October 2014` и `15:58:42 GMT` соответственно.

Дополнительно вы можете задать специальный формат, используя синтаксис, заданный [ICU Project](https://icu.unicode.org/),
который описан в руководстве ICU по следующему адресу:
<https://unicode-org.github.io/icu/userguide/format_parse/datetime/>. Также вы можете использовать синтаксис, который распознаётся
PHP-функцией [date()](https://www.php.net/manual/ru/function.date.php), используя строку с префиксом `php:`.

```php
// ICU форматирование
echo Yii::$app->formatter->asDate('now', 'yyyy-MM-dd'); // 2014-10-06
// PHP date() форматирование
echo Yii::$app->formatter->asDate('now', 'php:Y-m-d'); // 2014-10-06
```

### Часовые пояса <span id="time-zones"></span>

Для форматирования значений даты и времени Yii будет преобразовывать их в соответствии с
[[yii\i18n\Formatter::timeZone|настроенным часовым поясом]]. Поэтому предполагается, что входные значения будут в UTC,
если часовой пояс не был указан явно. По этой причине рекомендуется хранить все значения даты и времени в формате UTC,
предпочтительно в виде UNIX timestamp, которая всегда в часовом поясе UTC по определению. Если входное значение
находится в часовом поясе, отличном от UTC, часовой пояс должен быть указан явно, как в следующем примере:

```php
// при условии Yii::$app->timeZone = 'Europe/Berlin';
echo Yii::$app->formatter->asTime(1412599260); // 14:41:00
echo Yii::$app->formatter->asTime('2014-10-06 12:41:00'); // 14:41:00
echo Yii::$app->formatter->asTime('2014-10-06 14:41:00 CEST'); // 14:41:00
```

Если [[yii\i18n\Formatter::timeZone|часовой пояс форматтера]] не задан явно, используется
[[yii\base\Application::timeZone|часовой пояс приложения]], то есть тот же, что задан в
конфигурации PHP.

> Note: Поскольку правила для часовых поясов принимаются различными правительствами и могут часто меняться,
> вероятно, информация в базе данных часовых поясов на вашем сервере не самая свежая.
> Как обновить базу вы можете узнать из [руководства ICU](https://userguide.icu-project.org/datetime/timezone#TOC-Updating-the-Time-Zone-Data).
> Смотрите также: [Настройка вашего PHP окружения для интернационализации](tutorial-i18n.md#setup-environment).

Форматирование чисел <span id="numbers"></span>
-----------------------------------------------

Для форматирования числовых значений класс форматирования предоставляет следующие методы:

- [[yii\i18n\Formatter::asInteger()|integer]] — значение будет отформатировано как целое число, например `42`.
- [[yii\i18n\Formatter::asDecimal()|decimal]] — значение будет отформатировано как дробное число, состоящее из целого и
  дробной части, например: `2,542.123` или `2.542,123`.
- [[yii\i18n\Formatter::asPercent()|percent]] — значение будет отформатировано как процентное значение, например `42%`.
- [[yii\i18n\Formatter::asScientific()|scientific]] — значение будет отформатировано в научном формате, например: `4.2E4`.
- [[yii\i18n\Formatter::asCurrency()|currency]] — значение будет отформатировано в денежном формате, например: `£420.00`.
  Обратите внимание, чтобы эта функция работала правильно, локаль должна включать в себя часть со страной, например: `en_GB`
  или `en_US` (потому что указание только языка будет неоднозначным в этом случае).
- [[yii\i18n\Formatter::asSize()|size]] — значение будет отформатировано как количество байт в человеко-понятном формате,
  например: `410 kibibytes`.
- [[yii\i18n\Formatter::asShortSize()|shortSize]] — сокращённая версия [[yii\i18n\Formatter::asSize()|size]], например:
  `410 KiB`.

Форматирование чисел может быть скорректировано с помощью [[yii\i18n\Formatter::decimalSeparator|дробного разделителя]] и
[[yii\i18n\Formatter::thousandSeparator|тысячного разделителя]], которые были заданы в соответствии с локалью.

Для более сложной конфигурации [[yii\i18n\Formatter::numberFormatterOptions]] и [[yii\i18n\Formatter::numberFormatterTextOptions]]
могут быть использованы для настройки внутренне используемого [класса NumberFormatter](https://www.php.net/manual/ru/class.numberformatter.php).

Например, чтобы настроить максимальное и минимальное количество знаков после запятой, вы можете настроить свойство
[[yii\i18n\Formatter::numberFormatterOptions]] как в примере ниже:

```php
'numberFormatterOptions' => [
    NumberFormatter::MIN_FRACTION_DIGITS => 0,
    NumberFormatter::MAX_FRACTION_DIGITS => 2,
]
```

Остальное форматирование  <span id="other"></span>
--------------------------------------------------

Кроме форматирование даты, времени и чисел, Yii предоставляет набор других полезных средств форматирования для различных
ситуаций:

- [[yii\i18n\Formatter::asRaw()|raw]] — значение будет отображено как есть, это псевдо-форматирование, которое не даёт
  никакого эффекта,
  кроме значений `null`, которые будет отформатированы в соответствии с [[yii\i18n\Formatter::nullDisplay|nullDisplay]].
- [[yii\i18n\Formatter::asText()|text]] — значением будет экранированный от HTML текст.
  Это формат по умолчанию, используемый в [GridView DataColumn](output-data-widgets.md#data-column).
- [[yii\i18n\Formatter::asNtext()|ntext]] — значением будет экранированный от HTML текст с новыми строками,
  сконвертированными в разрывы строк.
- [[yii\i18n\Formatter::asParagraphs()|paragraphs]] — значением будет экранированный от HTML текст с параграфами,
  обрамлёнными в `<p>` теги.
- [[yii\i18n\Formatter::asHtml()|html]] — значение будет очищено, используя [[yii\helpers\HtmlPurifier|HtmlPurifier]], с целью предотвратить XSS
  атаки. Вы можете задать дополнительные параметры, такие как `['html', ['Attr.AllowedFrameTargets' => ['_blank']]]`.
- [[yii\i18n\Formatter::asEmail()|email]] — значение будет отформатировано как ссылка `mailto`.
- [[yii\i18n\Formatter::asImage()|image]] — значение будет отформатировано как тег картинки.
- [[yii\i18n\Formatter::asUrl()|url]] — значение будет отформатировано как ссылка <a>.
- [[yii\i18n\Formatter::asBoolean()|boolean]] — значение форматируется как логическое. По умолчанию `true` будет
  отображено как `Yes` и `false` как `No`, переведенное на язык приложения. Вы можете настроить это через свойство
  [[yii\i18n\Formatter::booleanFormat]].

`null` значения <span id="null-values"></span>
----------------------------------------------

Для значений `null` в PHP класс форматирования будет отображать вместо пустой строки маркер, по умолчанию это
`(not set)`, переведенный на язык приложения. Вы можете настроить свойство [[yii\i18n\Formatter::nullDisplay|nullDisplay]]
для установки собственного маркера. Если вы не хотите обрабатывать `null` значения, то установите свойство
[[yii\i18n\Formatter::nullDisplay|nullDisplay]] в `null`.
