datetime в Python — даты и время для аналитика

Коротко

Модуль datetime из стандартной библиотеки Python — основной инструмент работы с датами и временем. Аналитику он нужен для парсинга дат из CSV и JSON, фильтрации по периодам, расчёта разницы между датами и группировки по неделям/месяцам. На собеседованиях спрашивают про форматирование (strftime/strptime), арифметику дат (timedelta) и часовые пояса.

Основные классы

from datetime import date, time, datetime, timedelta

# date — только дата
d = date(2025, 3, 15)
print(d)  # 2025-03-15

# time — только время
t = time(14, 30, 0)
print(t)  # 14:30:00

# datetime — дата + время
dt = datetime(2025, 3, 15, 14, 30, 0)
print(dt)  # 2025-03-15 14:30:00

# timedelta — разница между датами
delta = timedelta(days=7)

На практике чаще всего используются datetime и timedelta.

Текущая дата и время

from datetime import datetime, date

# Текущие дата и время
now = datetime.now()
print(now)  # 2025-03-15 14:30:42.123456

# Только дата
today = date.today()
print(today)  # 2025-03-15

# UTC-время
utc_now = datetime.utcnow()

Создание из строки: strptime

Парсинг строки в datetime — одна из самых частых операций.

from datetime import datetime

# Парсинг строки
dt = datetime.strptime('15.03.2025', '%d.%m.%Y')
print(dt)  # 2025-03-15 00:00:00

dt = datetime.strptime('2025-03-15 14:30:00', '%Y-%m-%d %H:%M:%S')
print(dt)  # 2025-03-15 14:30:00

dt = datetime.strptime('Mar 15, 2025', '%b %d, %Y')
print(dt)  # 2025-03-15 00:00:00

Основные коды форматирования:

Код Значение Пример
%Y Год (4 цифры) 2025
%m Месяц (01-12) 03
%d День (01-31) 15
%H Час (00-23) 14
%M Минуты (00-59) 30
%S Секунды (00-59) 00
%B Месяц (полное название) March
%b Месяц (сокращённое) Mar
%A День недели Saturday
%w День недели (число, 0=вс) 6
%j День года (001-366) 074

Форматирование: strftime

Обратная операция — datetime в строку.

from datetime import datetime

dt = datetime(2025, 3, 15, 14, 30)

print(dt.strftime('%d.%m.%Y'))           # 15.03.2025
print(dt.strftime('%Y-%m-%d'))           # 2025-03-15
print(dt.strftime('%d %B %Y, %H:%M'))   # 15 March 2025, 14:30
print(dt.strftime('%Y-%m'))              # 2025-03 (для группировки по месяцам)
print(dt.strftime('%Y-W%W'))             # 2025-W10 (для группировки по неделям)

Мнемоника: strftime = format (в строку), strptime = parse (из строки).

Арифметика дат: timedelta

from datetime import datetime, timedelta

now = datetime(2025, 3, 15, 14, 0)

# Прибавить / отнять
tomorrow = now + timedelta(days=1)
last_week = now - timedelta(weeks=1)
two_hours_ago = now - timedelta(hours=2)

print(tomorrow)       # 2025-03-16 14:00:00
print(last_week)      # 2025-03-08 14:00:00
print(two_hours_ago)  # 2025-03-15 12:00:00

# Разница между датами
start = datetime(2025, 1, 1)
end = datetime(2025, 3, 15)
diff = end - start

print(diff)           # 73 days, 0:00:00
print(diff.days)      # 73
print(diff.total_seconds())  # 6307200.0

timedelta поддерживает: days, seconds, microseconds, milliseconds, minutes, hours, weeks. Месяцы и годы не поддерживаются — для этого используйте dateutil.relativedelta.

Извлечение компонентов

from datetime import datetime

dt = datetime(2025, 3, 15, 14, 30, 45)

dt.year     # 2025
dt.month    # 3
dt.day      # 15
dt.hour     # 14
dt.minute   # 30
dt.second   # 45

dt.weekday()   # 5 (0=пн, 6=вс)
dt.isoweekday()  # 6 (1=пн, 7=вс)

dt.date()  # date(2025, 3, 15) — только дата
dt.time()  # time(14, 30, 45) — только время

Аналитические примеры

Фильтрация по периоду

from datetime import datetime, timedelta

events = [
    {'event': 'login', 'ts': '2025-03-10 09:00:00'},
    {'event': 'purchase', 'ts': '2025-03-14 15:30:00'},
    {'event': 'login', 'ts': '2025-03-15 10:00:00'},
    {'event': 'logout', 'ts': '2025-03-16 18:00:00'},
]

cutoff = datetime.now() - timedelta(days=7)

recent = [
    e for e in events
    if datetime.strptime(e['ts'], '%Y-%m-%d %H:%M:%S') >= cutoff
]

Группировка по дням / неделям

from collections import Counter
from datetime import datetime

timestamps = [
    '2025-03-14 09:00', '2025-03-14 11:30',
    '2025-03-15 08:00', '2025-03-15 14:00', '2025-03-15 19:30',
    '2025-03-16 10:00',
]

# По дням
daily = Counter(
    datetime.strptime(ts, '%Y-%m-%d %H:%M').strftime('%Y-%m-%d')
    for ts in timestamps
)
# Counter({'2025-03-15': 3, '2025-03-14': 2, '2025-03-16': 1})

# По неделям
weekly = Counter(
    datetime.strptime(ts, '%Y-%m-%d %H:%M').strftime('%Y-W%W')
    for ts in timestamps
)

Расчёт retention window

from datetime import datetime, timedelta

signup_date = datetime(2025, 1, 15)

# Retention windows
day_1 = signup_date + timedelta(days=1)
day_7 = signup_date + timedelta(days=7)
day_30 = signup_date + timedelta(days=30)

# Проверка попадания события в окно
event_date = datetime(2025, 1, 22)
is_within_day7 = signup_date <= event_date <= day_7  # True

datetime в pandas

В pandas работа с датами удобнее благодаря pd.to_datetime и .dt-accessor:

import pandas as pd

df = pd.DataFrame({
    'user_id': [1, 2, 3],
    'created_at': ['2025-01-15', '2025-02-20', '2025-03-10']
})

# Конвертация строки в datetime
df['created_at'] = pd.to_datetime(df['created_at'])

# Извлечение компонентов
df['month'] = df['created_at'].dt.month
df['weekday'] = df['created_at'].dt.day_name()
df['quarter'] = df['created_at'].dt.quarter

# Фильтрация
recent = df[df['created_at'] >= '2025-02-01']

# Группировка по месяцам
monthly = df.groupby(df['created_at'].dt.to_period('M')).size()

pd.to_datetime умнее strptime — автоматически определяет формат в большинстве случаев. Подробнее о датах в SQL — в гайде по работе с датами SQL.

Часовые пояса

from datetime import datetime, timezone, timedelta

# UTC
utc_now = datetime.now(timezone.utc)

# Московское время (UTC+3)
msk = timezone(timedelta(hours=3))
msk_now = datetime.now(msk)

# С библиотекой zoneinfo (Python 3.9+)
from zoneinfo import ZoneInfo

msk_now = datetime.now(ZoneInfo('Europe/Moscow'))
utc_now = msk_now.astimezone(ZoneInfo('UTC'))

Правило: храните даты в UTC, конвертируйте в локальное время только для отображения.

Типичные ошибки

Путают strftime и strptime. strftime = format (datetime → строка). strptime = parse (строка → datetime).

Забывают о часовых поясах. datetime.now() — локальное время без таймзоны (naive). При сравнении с UTC-датами из БД будет расхождение. Используйте datetime.now(timezone.utc).

Месяцы и годы в timedelta. timedelta(months=1) — ошибка, такого параметра нет. Для добавления месяцев: dateutil.relativedelta(months=1) или ручная логика.

Формат даты не совпадает. strptime('15/03/2025', '%Y-%m-%d') — ValueError. Формат должен точно соответствовать строке.

Вопросы с собеседований

-- Чем отличается strftime от strptime? -- strftime (format) — datetime в строку. strptime (parse) — строка в datetime. Оба используют одинаковые коды форматирования (%Y, %m, %d и т.д.).

-- Как посчитать разницу между двумя датами в днях? -- (date2 - date1).days. Вычитание datetime/date возвращает timedelta, у которого есть атрибут .days.

-- Как сгруппировать данные по неделям в Python? -- dt.strftime('%Y-W%W') — номер недели. В pandas: df.groupby(df['date'].dt.isocalendar().week) или df.resample('W').

-- Что такое naive и aware datetime? -- Naive — без информации о часовом поясе (по умолчанию). Aware — с указанием timezone. Сравнение naive и aware вызовет TypeError.


Потренируйтесь решать задачи — откройте тренажёр с 1500+ вопросами для подготовки к собеседованиям аналитиков.

FAQ

datetime vs pandas Timestamp — в чём разница?

pandas.Timestamp — расширение datetime.datetime с наносекундной точностью и дополнительными методами. pd.to_datetime() возвращает Timestamp. Для аналитических задач pandas Timestamp удобнее, для скриптов без pandas — стандартный datetime.

Как обработать разные форматы дат в одном столбце?

pd.to_datetime(df['date'], format='mixed') или pd.to_datetime(df['date'], infer_datetime_format=True). pandas попытается определить формат автоматически. Для чистого Python — try/except с несколькими форматами.

Как работать с UNIX timestamp?

datetime.fromtimestamp(1710510000) — из UNIX timestamp в datetime. datetime.now().timestamp() — из datetime в UNIX timestamp. В pandas: pd.to_datetime(series, unit='s').

Как тренироваться

Задачи на работу с датами в Python и SQL — в тренажёре Карьерник. Больше вопросов — в разделе с примерами.