Модуль datetime в Python
Работа с датами и временем в Python через модуль datetime: date, time, datetime, timedelta, strftime, strptime и часовые пояса.
В Python нет встроенного типа данных для дат. Вместо этого модуль datetime из стандартной библиотеки предоставляет полный набор инструментов для создания, обработки, форматирования и разбора дат и времени. В этой главе рассматриваются все основные классы — date, time, datetime, timedelta и timezone — а также практические шаблоны, которые вы будете использовать регулярно.
Импорт модуля
Модуль datetime входит в состав стандартной библиотеки и не требует установки. Его можно импортировать двумя распространёнными способами:
# Import the module and qualify every name
import datetime
today = datetime.date.today()
# Import specific classes directly
from datetime import date, time, datetime, timedelta, timezone
today = date.today()Стиль from datetime import ... короче на практике и используется на протяжении всей этой главы.
Класс date
date представляет календарную дату (год, месяц, день) без компонента времени суток.
Создание объектов date
Доступ к атрибутам даты
Имея объект date, вы можете получить его год, месяц и день как целочисленные атрибуты, а также узнать день недели:
from datetime import date
d = date(2024, 6, 15)
print(d.year) # 2024
print(d.month) # 6
print(d.day) # 15
# weekday(): Monday = 0, Sunday = 6
print(d.weekday()) # 5 (Saturday)
# isoweekday(): Monday = 1, Sunday = 7
print(d.isoweekday()) # 6 (Saturday)Класс time
time представляет время суток (часы, минуты, секунды, микросекунды) независимо от конкретной даты.
from datetime import time
# time(hour, minute, second) — all arguments optional, default to 0
t = time(14, 30, 0)
print(t) # 14:30:00
print(t.hour) # 14
print(t.minute) # 30
print(t.second) # 0Класс time наиболее полезен, когда нужно хранить или сравнивать время без привязки к дате — например, «напомнить мне в 09:00 каждый день».
Класс datetime
datetime — основной рабочий класс. Он объединяет полную дату и время суток в одном объекте и используется в большинстве реальных программ.
Получение текущих даты и времени
from datetime import datetime
# Local system time (naive — no time zone)
now = datetime.now()
print(now) # e.g. 2024-06-15 14:30:45.123456
# UTC time
utc_now = datetime.utcnow()
print(utc_now) # e.g. 2024-06-15 18:30:45.123456Создание объектов datetime
from datetime import datetime, date, time
# Constructor: datetime(year, month, day, hour=0, minute=0, second=0)
dt = datetime(2024, 6, 15, 14, 30, 45)
print(dt) # 2024-06-15 14:30:45
# From an ISO 8601 string
dt2 = datetime.fromisoformat("2024-06-15T14:30:45")
print(dt2) # 2024-06-15 14:30:45
# Combine a date and a time object
combined = datetime.combine(date(2024, 6, 15), time(14, 30, 0))
print(combined) # 2024-06-15 14:30:00Доступ к атрибутам datetime
datetime предоставляет все атрибуты как из date, так и из time:
from datetime import datetime
dt = datetime(2024, 6, 15, 14, 30, 45)
print(dt.year) # 2024
print(dt.month) # 6
print(dt.day) # 15
print(dt.hour) # 14
print(dt.minute) # 30
print(dt.second) # 45
# Extract just the date or time part
print(dt.date()) # 2024-06-15
print(dt.time()) # 14:30:45Класс timedelta
timedelta представляет продолжительность — разницу между двумя моментами времени. Он используется для прибавления или вычитания временных интервалов из объектов date и datetime.
Создание и использование timedelta
from datetime import date, timedelta
today = date(2024, 6, 15)
# Add 30 days
future = today + timedelta(days=30)
print(future) # 2024-07-15
# Subtract 7 days
last_week = today - timedelta(weeks=1)
print(last_week) # 2024-06-08
# timedelta can express days, seconds, and microseconds
# Convenience arguments: days, seconds, microseconds, milliseconds, minutes, hours, weeks
delta = timedelta(hours=2, minutes=30)
print(delta) # 2:30:00Вычисление разницы между двумя датами
Вычитание одного объекта date или datetime из другого возвращает timedelta:
from datetime import date
start = date(2024, 1, 1)
end = date(2024, 6, 15)
diff = end - start
print(diff) # 166 days, 0:00:00
print(diff.days) # 166Это стандартный способ вычислить количество дней между двумя датами. Используйте .total_seconds() для объекта timedelta, если вам нужен интервал в секундах.
Форматирование дат и времени (strftime)
strftime («string format time») преобразует объект date или datetime в удобочитаемую строку. Вы передаёте строку формата, содержащую директивы, начинающиеся с %.
from datetime import datetime
dt = datetime(2024, 6, 15, 14, 30, 45)
print(dt.strftime("%Y-%m-%d")) # 2024-06-15
print(dt.strftime("%d/%m/%Y")) # 15/06/2024
print(dt.strftime("%A, %B %d, %Y")) # Saturday, June 15, 2024
print(dt.strftime("%I:%M %p")) # 02:30 PM
print(dt.strftime("%Y-%m-%d %H:%M:%S")) # 2024-06-15 14:30:45Основные директивы strftime
| Директива | Значение | Пример |
|---|---|---|
%Y | 4-значный год | 2024 |
%y | 2-значный год | 24 |
%m | Месяц с ведущим нулём | 06 |
%B | Полное название месяца | June |
%b | Сокращённое название месяца | Jun |
%d | День месяца с ведущим нулём | 15 |
%A | Полное название дня недели | Saturday |
%a | Сокращённое название дня недели | Sat |
%H | Час (24-часовой формат) | 14 |
%I | Час (12-часовой формат) | 02 |
%M | Минуты | 30 |
%S | Секунды | 45 |
%p | AM или PM | PM |
%j | День года | 167 |
%W | Номер недели в году | 24 |
Разбор дат и времени (strptime)
strptime («string parse time») — обратная операция к strftime: она преобразует строку в объект datetime. Необходимо указать строку формата, соответствующую входным данным.
Распространённая ловушка: strptime всегда возвращает datetime, даже если строка содержит только дату. Вызовите .date() для результата, если вам нужен обычный объект date.
Формат ISO 8601
Стандарт ISO 8601 (YYYY-MM-DDTHH:MM:SS) — наиболее переносимый способ передачи значений дат и времени. Python имеет встроенные вспомогательные функции для него:
from datetime import datetime
dt = datetime(2024, 6, 15, 14, 30, 45)
# Produce ISO 8601 string
print(dt.isoformat()) # 2024-06-15T14:30:45
# Parse ISO 8601 string (Python 3.7+)
dt2 = datetime.fromisoformat("2024-06-15T14:30:45")
print(dt2) # 2024-06-15 14:30:45Работа с временными метками
Unix-временная метка — это количество секунд, прошедших с 1 января 1970 года 00:00:00 UTC. Python может конвертировать временные метки в объекты datetime и обратно:
Часовые пояса
По умолчанию datetime.now() возвращает наивный datetime — без прикреплённой информации о часовом поясе. Присоединение объекта tzinfo делает его осведомлённым. Осведомлённые datetime необходимы, если ваша программа работает с пользователями из нескольких часовых поясов или хранит временные метки в базе данных.
Использование встроенного timezone
datetime.timezone предоставляет timezone.utc и позволяет создавать зоны с фиксированным смещением:
from datetime import datetime, timezone, timedelta
# Create an aware UTC datetime
utc_dt = datetime(2024, 6, 15, 14, 30, 45, tzinfo=timezone.utc)
print(utc_dt) # 2024-06-15 14:30:45+00:00
# Create a fixed +5:30 (India Standard Time) offset
ist_offset = timezone(timedelta(hours=5, minutes=30))
ist_dt = utc_dt.astimezone(ist_offset)
print(ist_dt) # 2024-06-15 20:00:45+05:30Использование zoneinfo (Python 3.9+)
Для реальных часовых поясов IANA, таких как America/New_York или Asia/Tokyo, используйте встроенный модуль zoneinfo (Python 3.9+). Он автоматически обрабатывает переход на летнее время.
from datetime import datetime, timezone
from zoneinfo import ZoneInfo
# UTC aware datetime
utc_dt = datetime(2024, 6, 15, 14, 30, 45, tzinfo=timezone.utc)
# Convert to Eastern Time (handles DST automatically)
eastern = ZoneInfo("America/New_York")
eastern_dt = utc_dt.astimezone(eastern)
print(eastern_dt) # 2024-06-15 10:30:45-04:00
# Convert to Tokyo time
tokyo = ZoneInfo("Asia/Tokyo")
tokyo_dt = utc_dt.astimezone(tokyo)
print(tokyo_dt) # 2024-06-15 23:30:45+09:00На Python 3.8 и более ранних версиях установите стороннюю библиотеку pytz для поддержки зон IANA.
Замена компонентов
replace() возвращает новый объект с изменёнными указанными полями. Исходный объект никогда не изменяется.
from datetime import datetime
dt = datetime(2024, 6, 15, 14, 30, 45)
# Change only the year
dt2 = dt.replace(year=2025)
print(dt2) # 2025-06-15 14:30:45
# Change hour and minute
dt3 = dt.replace(hour=9, minute=0, second=0)
print(dt3) # 2024-06-15 09:00:00Сравнение дат и времени
Объекты date и datetime поддерживают все стандартные операторы сравнения:
from datetime import date
d1 = date(2024, 1, 1)
d2 = date(2024, 6, 15)
print(d1 < d2) # True
print(d1 == d2) # False
# Find the earliest date
earliest = min(d1, d2)
print(earliest) # 2024-01-01Сравнивайте только осведомлённые datetime с осведомлёнными, а наивные с наивными — их смешение вызывает TypeError.
Всё вместе
Вот практический пример, объединяющий несколько концепций: он вычисляет, сколько дней осталось до будущего срока, и форматирует обе даты для отображения.
from datetime import date
deadline = date(2024, 12, 31)
today = date(2024, 6, 15)
days_left = (deadline - today).days
print(f"Today: {today.strftime('%B %d, %Y')}") # June 15, 2024
print(f"Deadline: {deadline.strftime('%B %d, %Y')}") # December 31, 2024
print(f"Days remaining: {days_left}") # 199Краткий справочник
| Задача | Код |
|---|---|
| Сегодняшняя дата | date.today() |
| Текущие дата и время | datetime.now() |
| Конкретная дата | date(2024, 6, 15) |
| Дата из строки | datetime.strptime(s, fmt) |
| Дата в строку | dt.strftime(fmt) |
| Формат ISO | dt.isoformat() / datetime.fromisoformat(s) |
| Прибавить/вычесть дни | d + timedelta(days=N) |
| Дней между датами | (d2 - d1).days |
| Конвертировать часовой пояс | dt.astimezone(ZoneInfo("Zone/Name")) |