Дата в Битриксе почти всегда хранится строкой в формате сайта (например, 18.05.2017 00:00:00), а вывести её нужно человеку – «02 июня, 2016», «18 мая» или «Проекту: 6 месяцев». Разберём, как получить любой из этих форматов штатными функциями ядра и не споткнуться на локали и часовом поясе.
Быстрый способ: FormatDate с нужным шаблоном
Проще всего скормить дату функции FormatDate(). Она принимает шаблон и метку времени (Unix timestamp), поэтому исходную строку сначала переводят в timestamp через MakeTimeStamp(). Для формата «02 июня, 2016» подойдёт шаблон d F, Y:
<?= FormatDate('d F, Y', MakeTimeStamp($arItem['ACTIVE_FROM'])) ?>
// 02 июня, 2016
Разберём символы шаблона: d – день с ведущим нулём, F – полное название месяца в родительном падеже («июня», а не «июнь»), Y – год из четырёх цифр. Названия месяцев берутся из активной языковой темы сайта, поэтому вручную склеивать их не нужно – Битрикс сам подставит русские склоняемые формы. Другие полезные символы: j – день без нуля, M – месяц сокращённо, H:i – часы и минуты.
Способ через ParseDateTime, когда нужен контроль над частями
Если дату надо разложить на составляющие (например, вывести день и месяц в разных HTML-блоках), исходную строку разбирают функцией ParseDateTime(). Она возвращает массив с ключами DD, MM, YYYY, HH, MI, SS. Название месяца достают из языкового файла ядра – сообщения MONTH_<N>_S хранят краткую форму в родительном падеже:
<?php foreach ($arResult['FIELDS'] as $code => $value): ?>
<?php if ($code === 'DATE_ACTIVE_FROM'): ?>
<div>
<?php
$d = ParseDateTime($value, FORMAT_DATETIME);
echo $d['DD'] . ' '
. ToLower(GetMessage('MONTH_' . intval($d['MM']) . '_S'))
. ', ' . $d['YYYY'];
?>
</div>
<?php endif ?>
<?php endforeach ?>
Здесь intval($d['MM']) убирает ведущий ноль из номера месяца (иначе получится ключ MONTH_06_S, которого нет), а ToLower() приводит название к нижнему регистру. В большинстве случаев этот громоздкий разбор не нужен – его заменяет один вызов FormatDate из первого способа.
Относительные форматы: «Проекту: 6 месяцев»
Кроме буквенных шаблонов у FormatDate есть служебные форматы для относительных дат. Формат Q (он же Ydiff) выводит, сколько времени прошло от указанной даты до текущей – «6 месяцев», «2 года»:
<?= 'Проекту: ' . FormatDate('Q', MakeTimeStamp($arItem['ACTIVE_FROM'])) ?>
Подробный разбор этого формата и его склонений – в отдельном гайде «Как отформатировать дату в формате Ydiff».
Подводные камни: локаль, часовой пояс и кэш
- Названия месяцев зависят от языковой темы. Если на странице выводится «June» вместо «июня» – проверьте, что активна русская локализация и подключены языковые файлы (
MONTH_*есть в русском наборе сообщений ядра). В многоязычном проекте формат меняется вместе с языком. - Падеж месяца. Символ
Fдаёт родительный падеж («2 июня»), а сообщениеMONTH_N(без суффикса_S) – именительный («Июнь»). Для строки «дата в предложении» нужен именноF/_S. - Часовой пояс.
MakeTimeStampтрактует строку в часовом поясе сайта. Если на проекте включены пользовательские часовые пояса (модуль главного модуля, автоопределение), время в выводе может «съезжать» – для дат без времени это неважно, но для событий сH:iучитывайте это. - Кэш компонента. Форматирование в шаблоне компонента кэшируется вместе с ним. Относительные форматы (
Q/Ydiff) внутри кэша «застывают» на момент генерации – их лучше считать вне кэша или сбрасывать кэш по времени.
Смежные приёмы работы с датами – в гайдах «Формат Ydiff (например, 2 года)», «Вывод текущего года на PHP» и «Счётчик обратного отсчёта в списке новостей». Как вывести конкретное поле элемента – см. «Как вывести определённое поле элемента инфоблока».