Нашли ошибку?
среднийpandas 3.0.6

Даты: to_datetime и .dt

Превратить строки в даты, достать месяц, день недели и час, посчитать промежутки между датами.

Нужно знать:Типы данных

Содержание статьи

Коротко

  • pd.to_datetime(s) превращает строки в тип datetime64. Свой формат — format="%d.%m.%Y", дата вида 01.03 — dayfirst=True, нераспознанные значения в NaT — errors="coerce".
  • Через .dt доступны части даты: .dt.year, .dt.month, .dt.day_name(), .dt.hour, .dt.date.
  • Разность дат — промежуток (Timedelta): .dt.days, .dt.total_seconds().
  • .dt.floor("D") округляет вниз до дня, часа и т. д.; .dt.strftime(...) форматирует в строку.
  • «Плюс месяц» с учётом календаря — pd.DateOffset(months=1).
  • В pandas 3 даты из строк хранятся с точностью до микросекунд (раньше — наносекунд).

Синтаксис

pd.to_datetime(s, format=None, dayfirst=False, errors="raise")
s.dt.year, s.dt.month, s.dt.day, s.dt.hour, s.dt.date
s.dt.day_name(), s.dt.floor("h"), s.dt.strftime("%d.%m.%Y")
(end - start).dt.days, (end - start).dt.total_seconds()
s + pd.DateOffset(months=1), s + pd.Timedelta(days=3)

Параметры

ПараметрЧто делаетПо умолчанию
formatформат строки: "%d.%m.%Y %H:%M", "ISO8601" или "mixed"определяется по первому значению
dayfirstв неоднозначных датах сначала день: 01.03 — 1 мартаFalse
errors"raise" — ошибка, "coerce" — NaT для нераспознанных"raise"
unitдля чисел: единица — "s", "ms", "us", "ns"None

Примеры

Данные для примеровиспользуются во всех примерах ниже
orders = pd.DataFrame({
    "created": ["2024-03-01 09:15", "2024-03-02 18:40", "2024-03-09 11:05"],
    "shipped": ["2024-03-03 10:00", "2024-03-02 21:10", "2024-03-12 16:30"],
})
Строки в даты
created = pd.to_datetime(orders["created"])
created
Вывод
0   2024-03-01 09:15:00
1   2024-03-02 18:40:00
2   2024-03-09 11:05:00
Name: created, dtype: datetime64[us]
Свой формат и dayfirst
print(pd.to_datetime(["01.03.2024", "15.04.2024"], format="%d.%m.%Y"))
pd.to_datetime(["01.03.2024"], dayfirst=True)
Вывод
DatetimeIndex(['2024-03-01', '2024-04-15'], dtype='datetime64[us]', freq=None)
DatetimeIndex(['2024-03-01'], dtype='datetime64[us]', freq=None)
Нераспознанные значения в NaT
pd.to_datetime(pd.Series(["2024-03-01", "не указано"]), errors="coerce")
Вывод
0   2024-03-01
1          NaT
dtype: datetime64[us]
Части даты через .dt
created = pd.to_datetime(orders["created"])
pd.DataFrame({
    "date": created.dt.date,
    "month": created.dt.month,
    "weekday": created.dt.day_name(),
    "hour": created.dt.hour,
})
Вывод
         date  month   weekday  hour
0  2024-03-01      3    Friday     9
1  2024-03-02      3  Saturday    18
2  2024-03-09      3  Saturday    11
Промежутки между датами
created = pd.to_datetime(orders["created"])
shipped = pd.to_datetime(orders["shipped"])
delay = shipped - created
print(delay)
delay.dt.total_seconds() / 3600                 # в часах
Вывод
0   2 days 00:45:00
1   0 days 02:30:00
2   3 days 05:25:00
dtype: timedelta64[us]
0    48.750000
1     2.500000
2    77.416667
dtype: float64
Округление и форматирование
created = pd.to_datetime(orders["created"])
print(created.dt.floor("D").tolist())           # до начала дня
created.dt.strftime("%d.%m.%Y")
Вывод
[Timestamp('2024-03-01 00:00:00'), Timestamp('2024-03-02 00:00:00'), Timestamp('2024-03-09 00:00:00')]
0    01.03.2024
1    02.03.2024
2    09.03.2024
Name: created, dtype: str
Плюс календарный месяц
created = pd.to_datetime(orders["created"])
created + pd.DateOffset(months=1)               # плюс календарный месяц
Вывод
0   2024-04-01 09:15:00
1   2024-04-02 18:40:00
2   2024-04-09 11:05:00
Name: created, dtype: datetime64[us]

Подводные камни

Разные форматы в одном столбце

Формат определяется по первой строке и применяется ко всем. Если форматы различаются, передайте format="ISO8601" (все ISO, но разной точности) или format="mixed".

Дата со временем и безошибка: ValueError
pd.to_datetime(pd.Series(["2024-03-01 10:00", "2024-03-05"]))   # формат определяется по первой строке
Ошибка
ValueError: time data "2024-03-05" doesn't match format "%Y-%m-%d %H:%M". You might want to try:
    - passing `format` if your strings have a consistent format;
    - passing `format='ISO8601'` if your strings are all ISO8601 but not necessarily in exactly the same format;
    - passing `format='mixed'`, and the format will be inferred for each element individually. You might want to use `dayfirst` alongside this.
format='ISO8601'
pd.to_datetime(pd.Series(["2024-03-01 10:00", "2024-03-05"]), format="ISO8601")
Вывод
0   2024-03-01 10:00:00
1   2024-03-05 00:00:00
dtype: datetime64[us]

Микросекунды вместо наносекунд

Тип и число
created = pd.to_datetime(orders["created"])
print(created.dtype)                            # pandas 3: микросекунды
created.astype("int64").iloc[0]                 # число в микросекундах, а не наносекундах
Вывод
datetime64[us]
np.int64(1709284500000000)