Методы вывода русских дат в PHP с примерами
Основные подходы к отображению русского времени в PHP
Как вывести дату на русском языке с помощью современного подхода на основе IntlDateFormatter?
Класс IntlDateFormatter из расширения intl предоставляет гибкие возможности для форматирования дат и времени с учетом локали. Это наиболее эффективное и рекомендуемое решение для PHP 5.3+.
<?php
$formatter = new IntlDateFormatter('ru_RU', IntlDateFormatter::LONG, IntlDateFormatter::NONE);
echo $formatter->format(new DateTime());
?>
10 марта 2025 г.
В примере используются константы LONG для даты и NONE для времени (не выводится). Можно комбинировать: MEDIUM, SHORT, FULL. Также можно задать часовой пояс и произвольный шаблон через метод setPattern().
Типичные проблемы и ошибки:
- Расширение intl не установлено. Решение: установка через менеджер пакетов (например,
apt install php-intlна Debian/Ubuntu) или включение в php.ini. - Локаль 'ru_RU' может отсутствовать. Можно попробовать 'ru' или проверить список доступных локалей командой
locale -a. - В некоторых окружениях (например, Windows) необходимо указать 'Russian' или 'Russian_Russia'.
- Вывод может быть в кодировке, отличной от UTF-8. Рекомендуется убедиться, что скрипт выводит в UTF-8.
Как отобразить русскую дату без расширения intl, используя устаревший метод strftime?
Функция strftime (доступна до PHP 8.1) в сочетании с setlocale позволяет форматировать дату в соответствии с выбранной локалью.
<?php
setlocale(LC_TIME, 'ru_RU.utf8', 'ru_RU', 'ru');
echo strftime('%d %B %Y', time());
?>
10 марта 2025
Обратите внимание на порядок параметров setlocale: сначала полное имя локали с кодировкой, затем сокращенные. В Windows может потребоваться 'Russian'. Код возвращает строку, которая может быть в кодировке локали (например, UTF-8 или Windows-1251).
Типичные проблемы:
- strftime объявлен устаревшим в PHP 8.1. Начиная с этой версии рекомендуется использовать IntlDateFormatter.
- setlocale возвращает false, если локаль не найдена. Рекомендуется проверять результат и использовать fallback.
- В серверных окружениях могут отсутствовать русские локали. Их можно установить через системные пакеты.
- Кодировка вывода может не совпадать с кодировкой страницы. Для перекодировки можно применить iconv.
Как сделать вывод русских названий месяцев, если локаль не работает?
Создать собственный массив месяцев и подставлять их в нужном падеже. Этот метод не зависит от системных локалей.
<?php
$months = [
1 => 'января', 'февраля', 'марта', 'апреля', 'мая', 'июня',
'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря'
];
$day = date('j');
$month = $months[date('n')];
$year = date('Y');
echo "$day $month $year года";
?>
10 марта 2025 года
Этот подход прост, но не учитывает склонения при разных числах (например, '1 марта' корректно, но '1 февраля'? В родительном падеже - 'февраля' - верно. Однако если требуется именительный падеж для заголовков, нужен другой массив. Для полной корректности потребуется более сложная логика.
Ограничения:
- Не поддерживается автоматическое склонение (падежи). Для профессиональных проектов лучше использовать библиотеку с поддержкой локали.
- Требуется ручное обслуживание (например, для дней недели, если нужно).
Как использовать библиотеку Carbon для локализации дат на русском?
Carbon расширяет DateTime и имеет встроенную поддержку локализации через setLocale() и метод isoFormat().
<?php
require 'vendor/autoload.php';
use Carbon\Carbon;
Carbon::setLocale('ru');
echo Carbon::now()->isoFormat('LL');
?>
10 марта 2025
Также доступны относительные даты: Carbon::now()->subDay()->diffForHumans() вернет '1 день назад' на русском.
Проблемы:
- Требуется установка через Composer, что может быть излишним для небольших проектов.
- Для корректной работы Carbon необходимы файлы локалей (поставляются в пакете).
- Не все методы локализованы под русский язык идеально (например, формат 'L' может дать неожиданный результат).
Расширенные примеры локализации русских дат
Пример 1: Вывод даты в родительном падеже с IntlDateFormatter (с кастомным шаблоном)
<?php
$formatter = new IntlDateFormatter('ru_RU', IntlDateFormatter::NONE, IntlDateFormatter::NONE);
$formatter->setPattern('d MMMM yyyy \'г.\'');
echo $formatter->format(new DateTime());
?>
10 марта 2025 г.
Шаблон 'd MMMM yyyy' выводит день, полное название месяца (в родительном падеже) и год. Символ 'г.' добавлен как литерал.
Пример 2: Вывод дня недели на русском (полное и сокращенное название)
<?php
$formatterFull = new IntlDateFormatter('ru_RU', IntlDateFormatter::NONE, IntlDateFormatter::NONE);
$formatterFull->setPattern('EEEE');
echo 'Полное: ' . $formatterFull->format(new DateTime());
$formatterShort = new IntlDateFormatter('ru_RU', IntlDateFormatter::NONE, IntlDateFormatter::NONE);
$formatterShort->setPattern('EEE');
echo '; Сокращенное: ' . $formatterShort->format(new DateTime());
?>
Полное: понедельник; Сокращенное: пн.
Следует обратить внимание на регистр: 'EEEE' - полное, 'EEE' - сокращенное (три буквы).
Пример 3: Относительные даты на русском с помощью Carbon
<?php
require 'vendor/autoload.php';
use Carbon\Carbon;
Carbon::setLocale('ru');
echo 'Вчера: ' . Carbon::yesterday()->diffForHumans() . "\n";
echo 'Завтра: ' . Carbon::tomorrow()->diffForHumans() . "\n";
echo '3 дня назад: ' . Carbon::now()->subDays(3)->diffForHumans();
?>
Вчера: 1 день назад Завтра: 1 день вперед 3 дня назад: 3 дня назад
Примечание: вывод для будущих дат может использовать 'после' или 'вперед'. Carbon позволяет настроить словарь через фабрику локалей.
Пример 4: Использование IntlDateFormatter с часовым поясом Москвы
<?php
$formatter = new IntlDateFormatter('ru_RU', IntlDateFormatter::FULL, IntlDateFormatter::FULL);
$formatter->setTimeZone('Europe/Moscow');
echo $formatter->format(new DateTime('now', new DateTimeZone('Europe/Moscow')));
?>
понедельник, 10 марта 2025 г. в 15:30:00 Московское стандартное время
Константа FULL выводит полные названия дня недели, месяца, года, времени и часового пояса на русском языке. Часовой пояс задается через setTimeZone().
Пример 5: Сравнение стилей форматирования (SHORT, MEDIUM, LONG, FULL)
<?php
$date = new DateTime();
$styles = ['SHORT', 'MEDIUM', 'LONG', 'FULL'];
foreach ($styles as $style) {
$const = constant("IntlDateFormatter::$style");
$formatter = new IntlDateFormatter('ru_RU', $const, IntlDateFormatter::NONE);
echo "$style: " . $formatter->format($date) . "\n";
}
?>
SHORT: 10.03.2025 MEDIUM: 10 мар 2025 г. LONG: 10 марта 2025 г. FULL: понедельник, 10 марта 2025 г.
Этот пример показывает, как изменить стиль для даты. Для времени можно задать вторым параметром аналогичные константы.
Пример 6: Fallback при отсутствии локали с использованием ручного массива
<?php
$months = ['января','февраля','марта','апреля','мая','июня','июля','августа','сентября','октября','ноября','декабря'];
$days = ['воскресенье','понедельник','вторник','среда','четверг','пятница','суббота'];
try {
$fmt = new IntlDateFormatter('ru_RU', IntlDateFormatter::LONG, IntlDateFormatter::NONE);
echo $fmt->format(new DateTime());
} catch (Exception $e) {
$d = getdate();
echo $d['mday'] . ' ' . $months[$d['mon']-1] . ' ' . $d['year'] . ' (' . $days[$d['wday']] . ')';
}
?>
10 марта 2025 (понедельник)
Если расширение intl не работает или локаль отсутствует, исключение перехватывается, и дата выводится с помощью массивов.
Пример 7: Форматирование даты из строки с русской локалью
<?php
$formatter = new IntlDateFormatter('ru_RU', IntlDateFormatter::LONG, IntlDateFormatter::NONE);
$timestamp = strtotime('2025-01-15');
echo $formatter->format($timestamp);
?>
15 января 2025 г.
IntlDateFormatter принимает как объект DateTime, так и числовой timestamp. Для строк рекомендуется использовать new DateTime($string).
Пример 8: Получение русских названий месяцев в именительном падеже (с заглавной буквы)
<?php
$formatter = new IntlDateFormatter('ru_RU', IntlDateFormatter::NONE, IntlDateFormatter::NONE);
$formatter->setPattern('LLLL');
$monthName = $formatter->format(new DateTime('2025-03-01'));
echo mb_convert_case($monthName, MB_CASE_TITLE, 'UTF-8');
?>
Март
По умолчанию IntlDateFormatter выводит месяц в родительном падеже (например, 'марта'). Используя паттерн 'LLLL' (полное название в именительном падеже) и функцию mb_convert_case, получаем 'Март' с заглавной буквы.
Пример 9: Вывод даты и времени с русскими названиями в формате 'сегодня', 'вчера' (без Carbon)
<?php
$today = new DateTime();
$yesterday = new DateTime('-1 day');
$formatter = new IntlDateFormatter('ru_RU', IntlDateFormatter::LONG, IntlDateFormatter::SHORT);
$relative = function($date) use ($today, $yesterday, $formatter) {
$diff = $today->diff($date);
if ($diff->days == 0) return 'сегодня ' . $formatter->format($date);
if ($diff->days == 1 && $diff->invert == 0) return 'вчера ' . $formatter->format($date);
return $formatter->format($date);
};
echo $relative($yesterday) . "\n";
echo $relative($today);
?>
вчера 9 марта 2025 г., 15:30 сегодня 10 марта 2025 г., 15:30
Простая реализация относительных дат без Carbon. Для точного определения 'вчера' можно также сравнить по календарным дням, а не по 24 часам.