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.0timedelta поддерживает: 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 # Truedatetime в 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 — в тренажёре Карьерник. Больше вопросов — в разделе с примерами.