Как отформатировать дату в формате Ydiff (например, "2 года")
6 мин 143 Обновлено 15 октября Сложность: Базовая
TL;DR
- FormatDate('Ydiff', MakeTimeStamp($date)) выводит разницу до сейчас: "2 года", "6 месяцев".
- Третий аргумент FormatDate задаёт точку отсчёта – тогда считается разница между двумя датами.
- Склонение "год/года/лет" подставляет русская локаль сайта.
- Результат "2 года" разбивают на число и слово через explode(' ', $diff).
- Ydiff округляет до одной старшей единицы – "2 года 3 месяца" одной строкой он не даст.
Иногда дату нужно показать не как "01.01.2014", а как прожитый интервал: "Мы на рынке 2 года", "Акция началась 6 месяцев назад". В 1С-Битрикс это делает относительный формат Ydiff функции FormatDate() – он сам вычисляет разницу между датой и текущим моментом и подбирает подходящую единицу измерения со склонением.
Что такое формат Ydiff
FormatDate() умеет не только раскладывать дату по шаблону (d.m.Y), но и выводить относительные интервалы. Формат Ydiff возвращает разницу между переданной датой и "сейчас", округляя до самой крупной подходящей единицы: годы, если прошло больше года; месяцы, если меньше; дальше – дни, часы, минуты. Результат – готовая строка вида "2 года" или "6 месяцев" с уже правильным русским склонением из локали сайта.
$first_date = '01.01.2014 00:00:00'; // исходная дата
$diff = FormatDate('Ydiff', MakeTimeStamp($first_date));
echo $diff; // например: 2 года
MakeTimeStamp() переводит строку в Unix-timestamp, а FormatDate('Ydiff', ...) сравнивает его с текущим временем. Третьим аргументом можно передать "точку отсчёта" вместо текущего момента – тогда считается разница между двумя датами:
echo FormatDate('Ydiff', MakeTimeStamp('01.01.2014'), MakeTimeStamp('01.01.2016'));
// 2 годаКак разбить результат на число и слово
Строка "2 года" – это число и единица через пробел. Если их нужно оформить по-разному (крупная цифра и подпись под ней), разбейте результат функцией explode():
$diff = FormatDate('Ydiff', MakeTimeStamp($first_date));
$parts = explode(' ', $diff); // ['2', 'года']
echo '<span class="num">' . $parts[0] . '</span>'; // 2
echo '<span class="unit">' . $parts[1] . '</span>'; // года
Родственные относительные форматы
Кроме Ydiff у FormatDate есть и "человекочитаемые" форматы вроде "X дней назад". Их удобно применять к датам публикаций и комментариев. Логика та же: функция сама выбирает единицу и склонение. Если же нужен обычный "02 июня, 2016", это уже задача буквенных шаблонов – она разобрана в гайде "Сменить формат даты в CMS Битрикс".
Подводные камни
- Склонение – из локали. Правильные формы "год / года / лет" подставляет русская языковая тема. На английской локали получите "years" – проверьте активный язык сайта.
- Только целые крупные единицы.
Ydiffне покажет "2 года 3 месяца" одной строкой – он округляет до одной старшей единицы. Для составного вывода считайте интервал вручную (например, черезDateTime::diff()чистого PHP) и собирайте строку сами. - Кэш "замораживает" интервал. Внутри кэшируемого шаблона компонента результат вычисляется в момент генерации кэша и потом не меняется, пока кэш жив. Для точных относительных дат считайте их вне кэша или сбрасывайте кэш по времени.
- Часовой пояс.
MakeTimeStampтрактует строку в часовом поясе сайта. При включённых пользовательских часовых поясах разница у разных посетителей может отличаться на границе суток. - Не путайте с датой публикации. Если исходная дата в будущем, "разница до сейчас" будет считаться от будущей точки – для обратного отсчёта до события используйте таймер, а не
Ydiff(см. гайды ниже).
Смежные приёмы работы с датами и временем – в гайдах "Сменить формат даты в CMS Битрикс", "Вывод текущего года на PHP", "Счётчик обратного отсчёта в списке новостей" и "Скрипт отсчёта времени до конца акции".
Частые вопросы
Как в Битрикс вывести дату как "2 года" или "6 месяцев"?
Используйте относительный формат FormatDate('Ydiff', MakeTimeStamp($date)). Функция сама вычисляет разницу между датой и текущим моментом и подбирает крупную единицу со склонением.
Можно ли посчитать разницу между двумя произвольными датами?
Да. Передайте вторую дату третьим аргументом: FormatDate('Ydiff', MakeTimeStamp($from), MakeTimeStamp($to)). Тогда точкой отсчёта будет не "сейчас", а $to.
Почему выводится "years" вместо "года"?
Склонение единиц берётся из активной языковой темы. Английский вариант означает, что на сайте активна не русская локализация.
Как показать "2 года 3 месяца" одной строкой?
Формат Ydiff округляет до одной старшей единицы и такой составной вывод не даёт. Для него посчитайте интервал вручную, например через DateTime::diff() чистого PHP, и соберите строку сами.
Почему относительная дата не обновляется на странице?
Внутри кэшируемого шаблона компонента результат вычисляется в момент генерации кэша и застывает. Считайте относительные даты вне кэша или настройте сброс кэша по времени.
Материалы по теме
Что почитать дальше по этой теме