Русские месяцы: названия дат словами
%B упрямо выводит October: названия месяцев strftime берёт из локали среды. Делаем словарь RU_MONTHS и печатаем «21 октября 2026» без единой локали.
Редакция Питоники
Задача звучит просто: напечатать «21 октября 2026». По шпаргалке кодов из прошлого урока напрашивается strftime('%d %B %Y') — день, полное имя месяца, год. Пробуем.
from datetime import datetime
d = datetime(2026, 10, 21, 14, 30, 45)
print(d.strftime('%d %B %Y'))
21 October 2026
Месяц вышел английским. Названия месяцев и дней strftime берёт не из Python, а из локали среды — языковых настроек операционной системы. По умолчанию действует C-локаль с английскими названиями, поэтому %B дал October. Теоретически есть функция setlocale, переключающая локаль процесса: после неё %B начинает говорить по-русски. Практически — так делать не стоит, и сейчас объясним почему.
Словарь RU_MONTHS: свой формат
Надёжнее не просить strftime говорить по-русски, а собрать русскую дату самим. В русском тексте дата выглядит как «21 октября 2026» — месяц стоит в родительном падеже. Словарь RU_MONTHS хранит месяцы сразу в этой форме, поэтому склонять в коде ничего не нужно: достал номер месяца d.month и получил готовое слово.
from datetime import datetime
RU_MONTHS = {
1: 'января', 2: 'февраля', 3: 'марта', 4: 'апреля',
5: 'мая', 6: 'июня', 7: 'июля', 8: 'августа',
9: 'сентября', 10: 'октября', 11: 'ноября', 12: 'декабря',
}
d = datetime(2026, 10, 21)
print(f'{d.day} {RU_MONTHS[d.month]} {d.year}')
21 октября 2026
Внутри f-строки три подстановки: d.day даёт 21, RU_MONTHS[d.month] — октября, d.year — 2026. Числа f-строка превращает в текст сама. Ключевое отличие от strftime: словарь лежит в вашем коде и не зависит ни от локали, ни от операционной системы — вывод одинаков на ноутбуке, на сервере и в браузерном интерпретаторе.
from datetime import datetime
RU_MONTHS = {
1: 'января', 2: 'февраля', 3: 'марта', 4: 'апреля',
5: 'мая', 6: 'июня', 7: 'июля', 8: 'августа',
9: 'сентября', 10: 'октября', 11: 'ноября', 12: 'декабря',
}
dates = [datetime(2026, 1, 1), datetime(2026, 5, 9), datetime(2026, 10, 21)]
for d in dates:
print(f'{d.day} {RU_MONTHS[d.month]} {d.year}')
1 января 2026 9 мая 2026 21 октября 2026
Словарь RU_MONTHS хранит месяцы сразу в нужном падеже, поэтому русская дата собирается одной f-строкой и одинакова на любой машине. Тот же приём работает и для дней недели: список RU_DAYS, проиндексированный номером дня из weekday(), даст слово среда. Но у дней недели есть собственная тонкость с нумерацией — ей посвящён урок про weekday.
Русская дата собрана. Дальше — isoformat: стандартный формат, которому не нужны ни шпаргалка кодов, ни словари, потому что его понимают все — базы данных, API и JavaScript.
Один месяц — два падежа
Словарь с месяцами в родительном падеже закрывает только один случай: дата с числом, «21 октября 2026». Но русский язык требует и второго. В заголовке отчёта нужен именительный падеж — «Октябрь 2026», в тексте письма — «с 21 октября», в названии месяца без числа — снова именительный. Одним словарём тут не обойтись, и мы держим два: один для дат с числом, второй для названий в заголовках. Это не перестраховка — «Октябрь 2026» и «21 октября 2026» стоят в соседних строках одного отчёта, и разница между ними сразу бросается в глаза.
from datetime import datetime
RU_MONTHS_GEN = {
1: 'января', 2: 'февраля', 3: 'марта', 4: 'апреля',
5: 'мая', 6: 'июня', 7: 'июля', 8: 'августа',
9: 'сентября', 10: 'октября', 11: 'ноября', 12: 'декабря',
}
RU_MONTHS_NOM = {
1: 'январь', 2: 'февраль', 3: 'март', 4: 'апрель',
5: 'май', 6: 'июнь', 7: 'июль', 8: 'август',
9: 'сентябрь', 10: 'октябрь', 11: 'ноябрь', 12: 'декабрь',
}
d = datetime(2026, 10, 21)
print(f'{d.day} {RU_MONTHS_GEN[d.month]} {d.year}')
print(f'{RU_MONTHS_NOM[d.month]} {d.year}')
21 октября 2026 октябрь 2026
Держите оба словаря рядом и называйте их по падежу, а не по смыслу: RU_MONTHS_GEN и RU_MONTHS_NOM. Когда словарь называется RU_MONTHS, через полгода никто не вспомнит, в каком падеже там месяцы, и поправит не ту строку. Мы в проектах выносят оба словаря в отдельный модуль с константами — их импортируют оттуда, а не пишут заново в каждом файле, который печатает дату.
Собираем дату один раз, а не в каждом месте
Как только русская дата нужна в нескольких местах — письмо, подпись в PDF, строка в уведомлении, — код с f-строкой начинает повторяться. Повторение f-строки это ещё полбеды: правило «сначала день, потом месяц, потом год» повторится тоже, и одна из копий рано или поздно соберётся неправильно. Выносим сборку в маленькую функцию — и все места гарантированно получают одинаковый результат.
from datetime import datetime
RU_MONTHS_GEN = {
1: 'января', 2: 'февраля', 3: 'марта', 4: 'апреля',
5: 'мая', 6: 'июня', 7: 'июля', 8: 'августа',
9: 'сентября', 10: 'октября', 11: 'ноября', 12: 'декабря',
}
def ru_date(d):
return f'{d.day} {RU_MONTHS_GEN[d.month]} {d.year}'
d = datetime(2026, 10, 21)
print(f'Заказ создан {ru_date(d)} года.')
Заказ создан 21 октября 2026 года.
Тот же приём работает и для дней недели. Список RU_DAYS, проиндексированный номером дня, отдаёт «среду» без всякой локали. Тонкость там одна — с какой нумерации считать день, о ней подробно в уроке про weekday.
from datetime import date
RU_DAYS = ['понедельник', 'вторник', 'среда', 'четверг', 'пятница', 'суббота', 'воскресенье']
d = date(2026, 10, 21)
print(RU_DAYS[d.weekday()])
среда
from datetime import datetime
RU_MONTHS_GEN = {
1: 'января', 2: 'февраля', 3: 'марта', 4: 'апреля',
5: 'мая', 6: 'июня', 7: 'июля', 8: 'августа',
9: 'сентября', 10: 'октября', 11: 'ноября', 12: 'декабря',
}
def ru_date(d):
return f'{d.day} {RU_MONTHS_GEN[d.month]} {d.year}'
for ds in ['2026-01-15', '2026-03-08', '2026-11-30']:
print(ru_date(datetime.fromisoformat(ds).date()))
15 января 2026 8 марта 2026 30 ноября 2026
Локаль — это настройка чужой машины, а словарь в вашем коде: русская дата, собранная вторым, одинаково выглядит на ноутбуке разработчика, на сервере в Ереване и в браузерном интерпретаторе.
Предложный падеж: «в октябре»
Питфолл выше говорил, что словарь покрывает только форму «число + месяц» и конструкции с предлогами в нём нет. Это правда — но решение простое, и стоит его назвать, потому что «в октябре» в отчёте нужно постоянно. Русский язык требует здесь предложного падежа: не «в октября» и не «в октябрь», а «в октябре». Добавляем третий словарь рядом с двумя первыми.
from datetime import datetime
RU_MONTHS_GEN = {
1: 'января', 2: 'февраля', 3: 'марта', 4: 'апреля',
5: 'мая', 6: 'июня', 7: 'июля', 8: 'августа',
9: 'сентября', 10: 'октября', 11: 'ноября', 12: 'декабря',
}
RU_MONTHS_PREP = {
1: 'январе', 2: 'феврале', 3: 'марте', 4: 'апреле',
5: 'мае', 6: 'июне', 7: 'июле', 8: 'августе',
9: 'сентябре', 10: 'октябре', 11: 'ноябре', 12: 'декабре',
}
d = datetime(2026, 10, 21)
print(f'{d.day} {RU_MONTHS_GEN[d.month]} {d.year}')
print(f'Отчёт за {RU_MONTHS_PREP[d.month]} {d.year}')
21 октября 2026 Отчёт за октябре 2026
Три словаря в одном файле — нормально, пока падежей не станет больше. Мы держали их с именами по падежу именно поэтому: RU_MONTHS_GEN, RU_MONTHS_NOM, RU_MONTHS_PREP. Когда словарь называется просто months, через полгода никто не вспомнит, в каком падеже там слова, и поправит не ту строку. Если в тексте понадобится четвёртый падеж — «к октябрю», — добавляйте словарь и переименовывайте все три, а не подгоняйте существующие.
Дни недели тоже склоняются
Список RU_DAYS из урока про weekday лежит в именительном падеже: понедельник, вторник, среда. Для даты с числом это годится, а вот конструкция «в среду» требует винительного падежа — «среду», а не «среда». Та же история, что и с месяцами: список имён дней нужен во всех падежах, а значит, нужен не один список, а по списку на падеж.
from datetime import date
RU_DAYS = ['понедельник', 'вторник', 'среда', 'четверг', 'пятница', 'суббота', 'воскресенье']
RU_DAYS_ACC = ['понедельник', 'вторник', 'среду', 'четверг', 'пятницу', 'субботу', 'воскресенье']
d = date(2026, 10, 21)
print(f'в {RU_DAYS_ACC[d.weekday()]}')
print(f'{RU_DAYS[d.weekday()]} — рабочий день')
в среду среда — рабочий день
У части слов формы совпадают: «понедельник» в именительном и винительном одинаковы, и менять там нечего. Меняются только те дни, где окончание отличает падеж, — среда и среду, пятница и пятницу. Отсюда практический совет: не пишите правила склонения в коде, а держите готовые формы в словаре. Правило склонения — это уже работа с языком, и в Python она лишняя.
Сначала предскажи ответ в голове — это главный навык программиста.
from datetime import datetime
RU_MONTHS = {
1: 'января', 2: 'февраля', 3: 'марта', 4: 'апреля',
5: 'мая', 6: 'июня', 7: 'июля', 8: 'августа',
9: 'сентября', 10: 'октября', 11: 'ноября', 12: 'декабря',
}
d = datetime(2026, 11, 7)
print(f'{d.day} {RU_MONTHS[d.month]} {d.year}')
from datetime import datetime
d = datetime(2026, 10, 21)
print(d.strftime('%d %B'))
from datetime import datetime
RU_MONTHS = {5: 'мая', 10: 'октября'}
d = datetime(2026, 5, 9)
print(f'{d.day} {RU_MONTHS[d.month]} {d.year}')
from datetime import datetime
RU_MONTHS_GEN = {10: 'октября'}
RU_MONTHS_NOM = {10: 'октябрь'}
d = datetime(2026, 10, 21)
print(f'{d.day} {RU_MONTHS_GEN[d.month]} {d.year}')
print(f'{RU_MONTHS_NOM[d.month]} {d.year}')
1. Почему strftime('%B') выводит October, а не «октября»?
2. Чем плох setlocale для русских дат?
3. В каком падеже словарь RU_MONTHS хранит месяцы?
4. Как получить из даты слово «октября»?
5. Что выведет f'{d.day} {RU_MONTHS[d.month]} {d.year}' для datetime(2026, 5, 9)?
6. Почему одного словаря месяцев может не хватить?
7. Что произойдёт при попытке напечатать «в октябре» через RU_MONTHS?
8. Зачем выносить сборку русской даты в отдельную функцию?
Допишите словарь RU_MONTHS: впишите февраль и март в нужном падеже. Затем выведите две даты по-русски: datetime(2026, 2, 14) как 14 февраля 2026 и datetime(2026, 3, 8) как 8 марта 2026.
Как вывести дату на русском в Python?
Заведите словарь RU_MONTHS с месяцами в родительном падеже ({10: 'октября'}) и соберите дату f-строкой: f'{d.day} {RU_MONTHS[d.month]} {d.year}' даст 21 октября 2026. Такой вывод одинаков на любой машине и не зависит от локали.
Почему %B в Python выводит месяц по-английски?
Потому что названия месяцев strftime берёт из локали операционной системы, а по умолчанию действует английская C-локаль. Python тут ни при чём — он лишь спрашивает у среды, как называется десятый месяц.
Урок 8: коды форматированияМожно ли включить русскую локаль через setlocale и забыть?
Лучше нет: имена локалей различаются между ОС (ru_RU.UTF-8 на Linux, Russian на Windows), а локаль глобальна для всего процесса. Код сломается или поведёт себя иначе на другой машине. Словарь месяцев — надёжнее и предсказуемее.
Как вывести день недели по-русски?
Тот же приём: список RU_DAYS с днями недели от понедельника до воскресенья и номер дня d.weekday() — RU_DAYS[d.weekday()] вернёт, например, среду. Тонкости нумерации дней разбираются в уроке про weekday.
Урок 12: weekday и isoweekdayНужно ли два словаря месяцев или хватит одного?
Двух. В родительном падеже («21 октября 2026») месяц стоит после числа, в именительном («Октябрь 2026») — сам по себе. Держите оба словаря рядом и называйте их по падежу: RU_MONTHS_GEN и RU_MONTHS_NOM.
Почему setlocale — плохой способ получить русскую дату?
Он меняет локаль всего процесса, а имя локали зависит от ОС: ru_RU.UTF-8 на Linux, Russian на Windows. Один и тот же код на другой машине либо выбросит ошибку, либо оставит английские названия. Словарь в коде работает везде одинаково — и тесты не зависят от настроек машины.
Урок 10: isoformatКак собрать русскую дату один раз и использовать везде?
Вынесите сборку в функцию: def ru_date(d): return f'{d.day} {RU_MONTHS_GEN[d.month]} {d.year}'. Дальше все места — письма, подписи, уведомления — зовут её и получают одинаковый результат.
Понравился урок? Сошлитесь на него
«Словарь RU_MONTHS хранит месяцы сразу в нужном падеже, поэтому русская дата собирается одной f-строкой и одинакова на любой машине.»
Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.
Что дальше
Осталось в разделе: 20 из 20. Прогресс хранится в вашем браузере.
Что читать дальше
Datetime · Урок 8
Коды форматирования strftime: полная шпаргалка
strftime превращает datetime в строку по шаблону из кодов: %Y — год, %m — месяц, %H — часы. Собираем полную шпаргалку с примерами вывода на одной фиксированной дате.
Datetime · Урок 10
isoformat и fromisoformat: ISO-даты
Один вызов — и datetime превращается в строку 2026-10-21T14:30:45. ISO-формат сортируется как текст, а fromisoformat читает его обратно без единого кода %.
Похожие уроки по темам
Подобраны автоматически по пересечению тем и ключевых слов.
openpyxl · Урок 9
Даты в Excel через openpyxl: запись, формат и арифметика
Пишем в ячейку настоящий datetime, показываем его по-русски маской DD.MM.YYYY и считаем дни между датами — а заодно узнаём, почему дату из файла нельзя сравнивать со строкой.
openpyxl датыopenpyxl дата в ячейке
SQLAlchemy · Урок 1
Что такое SQLAlchemy и ORM: первый движок
SQLAlchemy переводит классы Python в таблицы SQL и обратно. Создаём первый движок и выполняем первые запросы — всё прямо в браузере, без установки.
sqlalchemy orm простыми словамиsqlalchemy уроки на русском
Datetime · Урок 4
strftime: дата превращается в строку
Объект даты хорош для вычислений, а человеку нужна строка «21.10.2026». Один метод strftime и горстка кодов — и дата принимает любой вид.
strftime pythonpython strftime формат