Управляем временем в Python.
Разработчикам часто надо получить точное время с учётом часового пояса, чтобы вывести эти данные пользователю или запланировать выполнение функции. Если неправильно обработать данные, то можно нарушить логику программы и доставить неудобства юзерам.
Последствия ошибок с неправильной обработкой даты и времени бывают масштабными. Например, 1 марта 2010 года пользователи старых моделей PlayStation 3 столкнулись с массовым сбоем в работе консоли. Ошибка привела к тому, что игроки не могли пользоваться консолью. Проблема затронула миллионы устройств по всему миру и длилась около суток, пока Sony не выпустила исправление.
Сбой произошёл из-за ошибки с обработкой високосного года. Внутренние часы консоли приняли 2010 год за високосный. В результате 28 февраля 2010 года система перешла на несуществующую дату — 29 февраля 2010 года. Из-за этого сломались система проверки трофеев и соединение с PlayStation Network.
В этой статье мы рассказываем про модуль datetime в Python, который поможет удобно обрабатывать даты и не повторять ошибок Sony.
Что такое datetime в Python
- получать текущую дату и время;
- вычислять, сколько дней прошло с определённого события;
- синхронизировать данные с учётом разных часовых поясов;
- привязывать запуск функций в коде к указанному времени;
- выводить пользователю актуальную дату.
Как импортировать модуль datetime
Есть несколько способов подключить модуль datetime к проекту.
Импорт всего модуля
Если не хочется разбираться с тонкостями внутреннего устройства datetime, то можно импортировать сразу весь модуль, как единый объект:
import datetime
Тогда к классам и функциям модуля можно будет обращаться с помощью следующей конструкции:
datetime.<имя>
Этот способ подтянет в проект всё, что есть в директории модуля. Если в коде проекта будет использовать всего пару функций, то это не лучший способ. Можно сэкономить место и импортировать только то, что нужно.
Импорт конкретных имён с помощью from
Если в проекте нужны только некоторые модули, то для импорта можно использовать ключевое слово from:
from datetime import datetime, timedelta
В этом случае классы и функции можно будет использовать напрямую, без префикса datetime.
Импорт всех имён из модуля с помощью *
Можно перетащить в свой проект абсолютно все публичные функции, классы и переменные модуля. Делается это так:
from datetime import *
Импорт всего, что есть в модуле, может вызвать конфликт имён. Поэтому лучше не использовать этот способ в реальных проектах.
Основные классы в модуле datetime
Все операции со временем и датой осуществляются с помощью трёх основных классов модуля:
- date — класс для работы с датой. В нём содержится год, месяц и день;
- time — класс, который обрабатывает всё, что связано со временем и хранит в себе часы, минуты, секунды и микросекунды;
- datetime — класс, объединяющий в себе time и date.
Если вы не до конца понимаете, что такое классы и какую роль они играют в Python, то предлагаем отвлечься на наше руководство по основам ООП для питонистов.
Давайте рассмотрим, как устроены основные классы модуля datetime и как их использовать в коде проекта.
Класс date
Как уже говорили выше, класс date отвечает за работу с датами. Его конструктор последовательно принимает на вход год, месяц и число:
date(year, month, day)
Например, вот так можно задать определённую дату в коде проекта:
import datetime somedate = datetime.date(2030, 3, 25) print(somedate) # 2030-03-25
Если нужно получить или напечатать не всю дату, а только её часть, то можно использовать свойства year, month и day:
import datetime somedate = datetime.date(2030, 3, 25) print(somedate.year) # 2030 print(somedate.day) # 25
Компоненты даты можно менять с помощью функции replace(). Например, в примере кода выше сперва заменим год и день, а после выведем результат:
somedate = datetime.date(2030, 3, 25) print(somedate.year) # 2030 print(somedate.day) # 25 somedate = somedate.replace(year=2050, day=15) print(somedate.year) # 2050 print(somedate.day) # 15
Функция today()
В классе date есть функция today(), с помощью которой можно получить актуальную дату:
somedate = date.today() print(somedate) # Актуальная дата в формате yyyy-mm-dd
Важно учитывать, что функция получает данные от системных часов. Если на компьютере неправильно настроены дата и время, то Python также получит неверные данные.
Функция weekday()
Класс date не хранит в себе данные о дне недели, но мы можем получить их с помощью функции weekday(). Она возвращает число от 0 до 6, где 0 — понедельник, а 6 — воскресенье.
Проверим, какой день недели был 1 января 2025 года:
somedate = datetime.date(2025, 1, 1) someweekday = somedate.weekday() print(someweekday) # 2
Функция вывела число 2, значит, первого января 2025 года была среда, и это — правильно.
В международном стандарте ISO 8601, который описывает единый формат использования даты и времени, день недели принято задавать числом от 1 до 7, где 1 — понедельник, а 7 — воскресенье. Если надо, чтобы код возвращал данные в таком формате, то используйте функцию isoweekday():
somedate = datetime.date(2025, 1, 1) someweekday = somedate.isoweekday() print(someweekday) # 3
Класс time
Класс time отвечает за работу со временем. Его конструктор последовательно принимает на вход часы, минуты, секунды и микросекунды:
time(hour, min, sec, microsec)
В конструкторе класса time нет обязательных параметров, а это значит, что если мы что-то пропустим, то система инициализирует это нулями. Давайте попробует задать время с помощью класса time:
sometime = time(12, 10) print(sometime) # 12:10:00 sometime = time(12, 10, 31) print(sometime) # 12:10:31
С помощью функции replace() можно менять компоненты времени. Для примера давайте возьмём время из примера выше и заменим в нём часы и секунды:
sometime = time(12, 10, 31) print(sometime) # 12:10:31 sometime = sometime.replace(hour=8, second=4) print(sometime) # 08:10:04
Класс datetime
Класс datetime объединяет дату и время в одном объекте и позволяет работать с полными временными метками. Конструктор класса последовательно принимает на вход год, месяц, день, часы, минуты, секунды и микросекунды:
datetime(year, month, day, hour, min, sec, microsec)
Давайте попробуем задать дату и время с помощью класса datetime:
somedate = datetime(1999, 1, 23, 17, 55) print(somedate) # 1999-01-23 17:55:00
С помощью функции replace() также можно менять любой параметр класса. Например, заменим дату и часы:
somedate = datetime(1999, 1, 23, 17, 55) print(somedate) # 1999-01-23 17:55:00 somedate = somedate.replace(year=3025, hour=8) print(somedate) # 3025-01-23 08:55:00
Функция combine()
На примерах видно, что удобнее работать с классом datetime: в нём изначально есть все параметры, которые могут понадобиться. Если код в вашем проекте отдельно получает время и дату, то с помощью функции combine() вы можете объединить их в класс datetime:
some_date = date(2025, 12, 25) some_time = time(10, 30) some_datetime = datetime.combine(some_date, some_time) print(some_datetime) # 2025-12-25 10:30:00
Функция now()
С помощью функции now() можно получить текущую дату и время на основе системных часов:
curent_datetime = datetime.now() print(curent_datetime) # Актуальные дата и время
Функция timestamp()
В Unix-системах время исчисляется количеством секунд, которые прошли с полуночи 1 января 1970 года. От этой точки отсчитывают время компьютеры, смартфоны, программы и даже банкоматы.
С помощью функции timestamp() можно преобразовать объект datetime в метку Unix-времени:
curent_datetime = datetime.now() unix_time = curent_datetime.timestamp() print(unix_time) # 1743553145.838873
Арифметические операции со временем
Для осуществления арифметических операций в модуле datetime есть класс timedelta. Он показывает разницу между двумя моментами времени. С помощью timedelta также можно сравнивать даты и смещать временные метки.
Как найти разницу
Представьте, что вам надо узнать, сколько дней прошло с 1 марта 2018 года по 3 октября 2023 года. В уме такую задачу сходу не решить, а на Python решение займёт всего четыре строчки кода.
Сперва создадим обе даты:
first_date = date(2018, 3, 1) second_date = date(2023, 10, 2)
Теперь остаётся из большего вычесть меньшее и напечатать результат:
result = second_date – first_date print(result) # 2041 days, 0:00:00
Теперь мы знаем, что с 1 марта 2018 года по 3 октября 2023 года прошёл ровно 2041 день.
Как найти будущую дату
Представьте, что вы купили билеты на концерт любимой группы, который состоится ровно через 40 дней, а сегодня — 1 июня 2020 года. Давайте узнаем дату, на которую запланировано мероприятие.
Для этого сперва создадим объект текущей даты:
curent_date = date(2020, 6, 1)
Теперь с помощью timedelta обозначим, что концерт состоится через 40 дней:
curent_delta = timedelta(days=40)
Остаётся только прибавить к текущей дате дельту в 40 дней и вывести результат в консоль:
future_date = curent_date + curent_delta print(future_date) # 2020-07-11
Теперь мы знаем, что концерт запланирован на 11 июля 2020 года.
Как найти прошлую дату
Представьте, что сейчас на календаре 21 сентября 2014 года и вам надо узнать, какое число было 22 дня назад. Для этого сперва создадим текущую дату и зададим дельту в 22 дня:
curent_date = date(2014, 9, 21) curent_delta = timedelta(days=22)
Теперь просто вычтем из текущей даты нашу дельту и выведем результат в консоль:
future_date = curent_date – curent_delta print(future_date) # 2014-08-30
Выходит, что если сейчас на календаре 21 сентября 2014 года, то 22 дня назад было 30 августа.
Часовые пояса
Во всех примерах кода выше мы не учитывали часовые пояса и работали с «сырыми» данными. При этом в разных странах используются разные часовые пояса, и это важно учитывать в коде своих проектов. Особенно это важно в приложениях, в которых время — решающий параметр. Например, в банковских системах или в расписании поездов.
Как устроены часовые пояса
Чтобы обрабатывать часовые пояса в коде, надо понимать, как они устроены. Для регулирования времени во всём мире люди используют стандарт UTC (от англ. Coordinated Universal Time) — всемирное координированное время.
Есть нулевой часовой пояс — UTC+0, от которого рассчитывают смещения. Например, московское время смещено на +3 часа (UTC+3), а в Вашингтоне — столице США — на −4 часа (UTC−4). Если в нулевом часовом поясе полдень, то в Москве — 15:00.
Как создать часовой пояс в datetime
В модуле datetime для работы с часовыми поясами есть класс timezone. Создадим с его помощью московский часовой пояс, зная, что у него смещение на три часа вперёд:
moscow_tz = timezone(timedelta(hours=3), name=”MSK”)
В datetime есть встроенный объект часового пояса, равный UTC+0:
utc_tz = timezone.utc
Как узнать смещение часового пояса
Смещение от часового пояса UTC+0 можно узнать с помощью функции utcoffset(). Зададим дату со временем и узнаем, на сколько часов смещается время.
tz = timezone(timedelta(hours=3)) dt = datetime(2025, 3, 13, 14, 30, tzinfo=tz) offset = tz.utcoffset(dt) print(offset) # 3:00:00
Как узнать название часового пояса
Название часового пояса можно узнать с помощью функции tzname(). Сработает она только в том случае, если разработчик во время создания пояса передал параметр name:
tz = timezone(timedelta(hours=3), name=”MSK”) now = datetime.now(tz) print(tz.tzname(now)) # MSK
Преобразование строк в даты
В модуле datetime предусмотрена функция strptime(), с помощью которой можно преобразовать строку в дату. На вход эта функция получает саму строку и описание формата, в котором представлены данные.
Формат можно задать с помощью следующих кодов:
Символ | Описание |
---|---|
%d | День |
%m | Месяц |
%y | Год двумя цифрами |
%Y | Год четырьмя цифрами |
%H | Часы в 24-часовом формате |
%I | Часы в 12-часовом формате |
%M | Минуты |
%S | Секунды |
%j | Порядковый номер дня в году от 001 до 366 |
%Z | Часовой пояс |
Например вот так можно конвертировать обычную строку в объект datetime:
some_date = datetime.strptime(“02/02/2010 19:44”, “%d/%m/%Y %H:%M”) print(some_date) # 2010-02-02 19:44:00
Преобразование дат в строки
Если надо, наоборот, из объекта даты получить строки, то можно использовать функцию strftime(). Она принимает на вход дату и формат, в котором надо записать данные. Для записи формата применяют те же коды, что и в функции strptime().
Для примера создадим объект datetime и преобразуем его в строки с разным форматированием:
somedate = datetime(1999, 1, 23, 17, 55) print(somedate) # 1999-01-23 17:55:00 formatted_somedate = somedate.strftime(“%d.%m.%Y %H:%M”) print(formatted_somedate) # 23.01.1999 17:55 formatted_somedate = somedate.strftime(“%d.%m.%Y”) print(formatted_somedate) # 23.01.1999 formatted_somedate = somedate.strftime(“%H:%M”) print(formatted_somedate) #17:55
Что запомнить
- datetime — модуль стандартной библиотеки Python, предназначенный для работы с датой и временем.
- С помощью datetime разработчики могут получать актуальное время с учётом часового пояса, находить прошлые и будущие даты.
- Для управления часовыми поясами предусмотрен класс timezone.
- datetime используют в программах, в которых важна привязка ко времени. Например, в расписании поездов или в электронном блокноте, который рассылает напоминания в указанное время.
- Также datetime можно использовать в системных утилитах, например, для привязки логов ко времени.
Модуль — файл с кодом на Python, в котором находятся реализации функций и классов. Его можно импортировать в другие файлы проекта.
Микросекунда — единица времени, равная одной миллионной секунды.
Конструктор класса — это специальный метод, который вызывается автоматически при создании нового объекта класса. Он нужен для инициализации свойств этого объекта.