strftime: дата превращается в строку
Объект даты хорош для вычислений, а человеку нужна строка «21.10.2026». Один метод strftime и горстка кодов — и дата принимает любой вид.
Редакция Питоники
Для вычислений объект из прошлых уроков идеален, но наружу его так не отдашь: пользователю нужна «21.10.2026», отчёту — «2026-10-21», письму — «21 октября». Печатать дату руками из шести полей — значит склеивать нули и переживать о точках. В Python это одна строка: метод strftime, «string from time» — строка из времени.
Шаблон из кодов
strftime принимает шаблон — обычную строку, в которой специальные коды со знаком процента заменяются значениями полей. Код в шаблоне заменяется значением поля, а все остальные символы — точки, дефисы, пробелы — печатаются как есть. Главные коды: %d — день, %m — месяц, %Y — год с веком, каждый двумя цифрами, где нужно.
from datetime import datetime
moment = datetime(2026, 10, 21, 12, 0)
print(moment.strftime('%d.%m.%Y'))
print(moment.strftime('%Y-%m-%d'))
print(moment.strftime('%d.%m.%Y %H:%M'))
21.10.2026 2026-10-21 21.10.2026 12:00
Время в шаблоне
from datetime import datetime
moment = datetime(2026, 10, 21, 12, 0)
print(moment.strftime('%H:%M'))
print(moment.strftime('%H:%M:%S'))
print(moment.strftime('%d.%m.%Y, %H:%M'))
12:00 12:00:00 21.10.2026, 12:00
К %d.%m.%Y добавились коды времени: %H — часы от 00 до 23, %M — минуты, %S — секунды, тоже с ведущими нулями: в 9:05 утра %H:%M даст «09:05». Метод возвращает строку и ничего не меняет в самом объекте — strftime можно вызывать хоть десять раз с разными шаблонами. Работает он и у date: date(2026, 10, 21).strftime('%d.%m.%Y') даст «21.10.2026».
| Код | Что подставит | Для момента 21.10.2026 12:00 |
|---|---|---|
| %Y | год с веком | 2026 |
| %m | месяц двумя цифрами | 10 |
| %d | день двумя цифрами | 21 |
| %H | часы, 00–23 | 12 |
| %M | минуты двумя цифрами | 00 |
| %S | секунды двумя цифрами | 00 |
Названия месяцев и дней: честно про локаль
from datetime import datetime
moment = datetime(2026, 10, 21, 12, 0)
print(moment.strftime('%B'))
print(moment.strftime('%b'))
print(moment.strftime('%A, %d %B %Y'))
October Oct Wednesday, 21 October 2026
Коды %B и %b — полное и краткое название месяца, %A и %a — название дня недели. Подставляются они по локали среды, где исполняется код: в песочнице на этой странице локаль английская, поэтому October и Wednesday — а не «Октябрь» и «среда». О том, как получить русские названия и собрать «21 октября 2026», — целый урок 9; полная таблица всех кодов форматирования ждёт в уроке 8.
Один объект — сколько угодно строк
Самое частое применение strftime в рабочем коде — один и тот же момент превращается в разные строки для разных потребителей. Отчёт для бухгалтерии, строка в лог, подпись в письме, имя файла: момент один, форматов четыре. Держите объект и форматируйте на выходе, а не на входе — тогда любая правка шаблона не ломает расчёты.
from datetime import datetime
moment = datetime(2026, 10, 21, 9, 5, 7)
print(moment.strftime('%d.%m.%Y'))
print(moment.strftime('%Y-%m-%d'))
print(moment.strftime('%d.%m.%Y %H:%M:%S'))
print(moment.strftime('%H:%M'))
21.10.2026 2026-10-21 21.10.2026 09:05:07 09:05
Шаблоны выносят в константы
Как только шаблон используется в двух местах, он заслуживает имени. Строки с процентами прямо в коде — это классика, из-за которой через год никто не может сказать, что значит %d.%m.%Y в конкретном отчёте. Мы в проектах держим константы с именами, говорящими о назначении, а не о виде: DATE_FORMAT для даты, ISO_FORMAT для машинного формата. Правило простое — если шаблон повторился дважды, у него должно быть имя.
from datetime import datetime
DATE_FORMAT = '%d.%m.%Y'
ISO_FORMAT = '%Y-%m-%d'
moment = datetime(2026, 10, 21)
print(moment.strftime(DATE_FORMAT))
print(moment.strftime(ISO_FORMAT))
21.10.2026 2026-10-21
from datetime import datetime
moment = datetime(2026, 10, 21)
print(moment.strftime('скидка %d%%'))
print(moment.strftime('скидка %d%% на всё'))
скидка 21% скидка 21% на всё
Где это нужно на практике: имя файла и подпись
Случай, где формат выбирают не для красоты, а чтобы сортировка работала. Выгрузку за вчера кладут в файл report_2026-10-21.csv — и папка с выгрузками за месяц сортируется по дате сама, без всякой разметки. Формат %Y-%m-%d здесь единственный разумный: он монотонный, а русский %d.%m.%Y в имени файла дал бы report_05.10.2026.csv рядом с report_12.09.2026.csv, и по алфавиту они встали бы не в том порядке.
from datetime import datetime
moment = datetime(2026, 10, 21, 9, 5)
name = 'report_' + moment.strftime('%Y-%m-%d') + '.csv'
print(name)
report_2026-10-21.csv
Отдельно про имя файла: двоеточие в нём использовать нельзя — на Windows это запрещённый символ, и файл просто не создастся. Тот же %H:%M в шаблоне выдаст «14:30», а для имени файла приходится писать %H-%M или %H%M. Мелочь, на которую уходит час, когда в проде впервые падает выгрузка.
Шаблон — это не украшение, а контракт: он решает, в каком виде дата попадёт в лог, в отчёт или в имя файла, и потому меняется вместе с требованиями к этим трём вещам.
Коды, результат которых зависит от машины
Большинство кодов strftime ведут себя одинаково везде: %d.%m.%Y даст «21.10.2026» и на ноутбуке, и в контейнере. Но есть исключения, и они кусаются именно там, где код кажется простым. Код %c печатает дату и время в формате, заданном операционной системой: у нас он даёт «Wed Oct 21 14:30:45 2026», а на другой машине с другой локалью — другой вид. Тот же случай у %x (дата) и %X (время): сейчас это «10/21/26» и «14:30:45», но в другой локали придёт «21.10.26».
Ловушка здесь в том, что на своей машине такой код выглядит вполне рабочим: он печатает, выглядит осмысленно, никто его не проверяет. Ошибка всплывает на другой машине — в CI, на сервере, у коллеги. И выглядит это как «вчера работало, сегодня сломалось», хотя код не менялся.
Отдельная история — код %Z с именем часового пояса. У момента без привязки к зоне он пустой, у осознанного момента отдаёт что-то вроде MSK, и это значение тоже зависит от того, как настроена система. Для имени зоны у нас есть только один надёжный источник: tzinfo самого объекта. Всё, что связано с зонами, разбирается в уроке 14, а здесь достаточно понимать, что %Z в шаблоне — это не то, что можно класть в сравнение.
| Код | Что печатает | Стабилен? |
|---|---|---|
| %d.%m.%Y | 21.10.2026 | да, поля перечислены явно |
| %Y-%m-%d %H:%M | 2026-10-21 14:30 | да |
| %c | дата и время в формате системы | нет, задано операционной системой |
| %x | дата в формате системы | нет, зависит от локали |
| %X | время в формате системы | нет, зависит от локали |
| %Z | имя зоны; у момента без зоны пусто | нет, зависит от настроек |
Проверка, которая закрывает вопрос раз и навсегда: если строка из шаблона уходит в базу, в лог или в API — она должна сортироваться как дата и разбираться обратно без потерь. %Y-%m-%d %H:%M удовлетворяет обоим условиям, %c не удовлетворяет ни первому, ни второму. Мы держим в проектах одно правило: шаблон либо перечисляет поля сам, либо это isoformat(). Всё остальное — для глаз, а не для хранения.
Сначала предскажи ответ в голове — это главный навык программиста.
from datetime import datetime
moment = datetime(2026, 3, 8, 9, 5)
print(moment.strftime('%d.%m.%Y'))
from datetime import datetime
moment = datetime(2026, 10, 21, 12, 0)
print(moment.strftime('%H:%M:%S'), moment.strftime('%d.%m.%Y, %H:%M'))
from datetime import datetime
moment = datetime(2026, 10, 21, 12, 0)
s = moment.strftime('%d.%m.%Y')
print(type(s))
1. Что вернёт moment.strftime('%d.%m.%Y') для datetime(2026, 10, 21)?
2. Что произойдёт с точками и пробелами в шаблоне strftime?
3. Что даст strftime('%H:%M') в 9:05 утра?
4. Почему moment.strftime('%B') в песочнице вернёт October, а не «Октябрь»?
5. Меняет ли strftime сам объект datetime?
6. Какой шаблон даст строку, которая сортируется как дата?
7. Что напечатает moment.strftime('скидка %d%%')?
8. Почему шаблон стоит выносить в константу?
9. Почему в имени файла нельзя подставлять время через %H:%M?
Отформатируй момент премьеры — 8 марта 2027 года, 19:30 — тремя способами: «08.03.2027», затем «2027-03-08», затем «08.03.2027 19:30». Каждый вариант выведи отдельной строкой.
Как перевести дату в строку в Python?
Методом strftime с шаблоном из кодов: moment.strftime('%d.%m.%Y') вернёт '21.10.2026'. Код %d — день, %m — месяц, %Y — год, остальные символы шаблона печатаются как есть. Метод работает и у datetime, и у date.
Урок 4: strftimeЧто значат %Y, %m, %d в strftime?
Это коды форматирования: %Y — год с веком, %m — месяц двумя цифрами, %d — день двумя цифрами. Регистр важен: %m — месяц, а %M — минуты; %d — день, а %D — сокращение вида «10/21/26». Полная таблица кодов — в уроке 8.
Урок 8: коды форматированияПочему strftime даёт английские названия месяцев?
Коды %B (месяц) и %A (день недели) берут названия из локали среды, где исполняется код. В песочнице курса и в большинстве серверных сред локаль английская. Русские названия получают своими руками — словарём месяцев и склонением, это тема урока 9.
Урок 9: русские датыКак получить дату без времени в строке?
Использовать шаблон только из кодов даты: moment.strftime('%d.%m.%Y') даст «21.10.2026». Другой вариант — сначала извлечь дату методом .date(), потом форматировать: moment.date().strftime('%Y-%m-%d').
Урок 2: date, time и datetimeКак напечатать процент в строке strftime?
Удвоить знак: 'скидка %d%%' напечатает «скидка 21%». Одинокий % в конце шаблона — ошибка: в Python 3.13 и новее это ValueError: Invalid format string, в более старых версиях знак мог пропасть молча. Правило не менялось: любой процент в шаблоне удваивается.
Какой формат выбрать для имени файла с датой?
%Y-%m-%d. Он монотонный, поэтому файлы за месяц сортируются по дате прямо в списке. Русский %d.%m.%Y в имени файла не годится: report_05.10.2026.csv встанет раньше report_12.09.2026.csv, хотя по датам наоборот.
Можно ли вызвать strftime у объекта date?
Да, метод есть и у date, и у datetime. date(2026, 10, 21).strftime('%d.%m.%Y') вернёт «21.10.2026». Коды времени у date, понятно, ничего не дадут — у него просто нет полей часов.
Урок 2: date, time и datetimeПонравился урок? Сошлитесь на него
«Код в шаблоне заменяется значением поля, а все остальные символы — точки, дефисы, пробелы — печатаются как есть.»
Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.
Что дальше
Осталось в разделе: 20 из 20. Прогресс хранится в вашем браузере.
Что читать дальше
Datetime · Урок 3
now и today: текущий момент
Фиксированные даты хороши для примеров, а для логов и дедлайнов нужен настоящий сейчас. Учимся получать текущий момент — и понимать, почему вывод перестаёт быть предсказуемым.
Datetime · Урок 5
strptime: строка превращается в дату
Лог, форма и таблица присылают даты строками — для вычислений нужен объект. Учим strptime читать строку по шаблону и отличать настоящий формат от почти настоящего.
Datetime · Урок 8
Коды форматирования strftime: полная шпаргалка
strftime превращает datetime в строку по шаблону из кодов: %Y — год, %m — месяц, %H — часы. Собираем полную шпаргалку с примерами вывода на одной фиксированной дате.
Похожие уроки по темам
Подобраны автоматически по пересечению тем и ключевых слов.
openpyxl · Урок 9
Даты в Excel через openpyxl: запись, формат и арифметика
Пишем в ячейку настоящий datetime, показываем его по-русски маской DD.MM.YYYY и считаем дни между датами — а заодно узнаём, почему дату из файла нельзя сравнивать со строкой.
openpyxl датыopenpyxl дата в ячейке
Строки · Урок 12
format() и старый процент: история форматирования
До f-строк текст собирали методом format, а до него — процентом. Эти способы живы в миллионах строк чужого кода: учимся читать их свободно и понимать, почему f-строки победили.
форматирование строк pythonpython формат строки
Datetime · Урок 9
Русские месяцы: названия дат словами
%B упрямо выводит October: названия месяцев strftime берёт из локали среды. Делаем словарь RU_MONTHS и печатаем «21 октября 2026» без единой локали.
русские даты pythonpython дата на русском