Методы вывода русских дат в PHP с примерами

Раздел: PHP -> Дата и время в 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 часам.

Русское время в PHP - comments

En
Php ru time (php)