2025, Oct 20 15:16

Почему date_format в pandas.to_csv не срабатывает и что делать

Почему date_format в pandas.to_csv не работает для Python date и как форматировать даты в CSV: to_datetime + strftime или Arrow date32. С примерами и кодом.

Экспорт дат из pandas в CSV с ожиданием, что сработает параметр date_format, может разочаровать, если данные представлены «чистыми» объектами даты из Python. Форматтер молча ничего не делает, и на выходе — ISO‑подобные значения. Ниже — почему так происходит и как это исправить без изменения логики вашего конвейера данных.

Симптом

Вы просите pandas отформатировать даты при экспорте, но результат не соответствует заданному шаблону:

import pandas as p
import datetime as dt
sheet = p.DataFrame([dt.datetime.now().date()])
text_csv = sheet.to_csv(date_format="%Y %b")
print(text_csv)
# Вывод
#,0
#0,2025-07-31

CSV показывает «сырую» дату: 2025-07-31, а не ожидаемое 2025 Jul.

Что происходит под капотом

Pandas пока не поддерживает собственный отдельный тип «дата». Он опирается на NumPy, где есть единый 64‑битный тип даты-времени — datetime64[ns]. Поэтому обычные даты сохраняются как Object. Из‑за этого функции, работающие с датой‑временем — в том числе аксессор .dt и параметр date_format в to_csv — к таким столбцам не применяются.

Как воспроизвести несоответствие типов

Стоит проверить dtype — и несоответствие сразу видно: date попадает в object, тогда как datetime — в datetime64[ns]. Именно это и «ломает» форматирование.

import pandas as p
from datetime import date
col = p.Series([date.today()])
print(col.dtype)
# Вывод
# object

Попытка отформатировать через .dt подтверждает, что серия не распознана как datetimelike:

col.dt.strftime("%Y %b")
# ...
# AttributeError: Can only use .dt accessor with datetimelike values. Did you mean: 'at'?

Решение и рабочие примеры

Исправление состоит в том, чтобы сначала привести значения из object к типу, понимающему дату‑время, а затем форматировать. Когда серия становится datetimelike, strftime работает как нужно. После этого можно записывать уже отформатированные строки в CSV.

import pandas as p
from datetime import date
raw_dates = p.Series([date.today()])
formatted = p.to_datetime(raw_dates).dt.strftime("%Y %b")
print(formatted)
# Вывод
# 0    2025 Jul

Если вам нужен тип с «родной» поддержкой дат, используйте серию на базе Arrow — тогда strftime можно применять напрямую.

import pandas as p
from datetime import date
arrow_dates = p.Series([date.today()], dtype="date32[pyarrow]")
pretty = arrow_dates.dt.strftime("%Y %b")
print(pretty)
# Вывод
# 0    2025 Jul
# dtype: string[pyarrow]

Почему это важно

Экспорт в CSV — это граница между системами. Если ваш конвейер зависит от стабильного формата дат, незаметная запись дат как object может привести к неожиданностям при разборе дальше по цепочке. Понимание того, что «чистые» даты хранятся как object, а не datetimelike, помогает избежать хрупких экспортов и неожиданных ошибок при операциях с .dt.

Итоги

Если date_format в to_csv не срабатывает, сначала проверьте dtype. Если там object, преобразуйте к типу с поддержкой даты‑времени, отформатируйте через strftime и экспортируйте. Либо сразу используйте серию дат на базе Arrow, чтобы получить нужную семантику с самого начала. Оба подхода возвращают предсказуемый и явный контроль над тем, как выглядят ваши даты в CSV.

Статья основана на вопросе на StackOverflow от Hugo Trentesaux и ответе Panagiotis Kanavos.