В Python timedelta – это тип данных в модуле datetime, используемый для представления длительности времени или разницы между двумя точками во времени.
Многие наборы данных реального мира содержат даты и время, и одной из распространенных операций в науке о данных является вычисление разницы во времени между двумя точками.
Единицы, которые мы используем для измерения даты и времени (годы, месяцы, дни, часы, минуты, секунды), – не самые простые для работы, особенно когда они имеют неравномерную длину.
Но тип данных timedelta, входящий в состав модуля datetime в Python, справляется со сложностями, связанными с определением временных интервалов.
Давайте начнем с очень краткого ответа на вопрос о том, что собой представляет timedelta в Python, а затем продолжим более подробно.
Что такое timedelta в Python
Два наиболее важных и часто используемых типа данных из модуля datetime – timedelta
и datetime
. Объекты datetime
представляют конкретные точки во времени, например, 1 января 2024 года в 10:30 утра. А объекты timedelta
представляют длительности или интервалы между двумя точками. Разница между этими типами аналогична разнице между ответами на вопросы «Когда?» (datetime) и «Как долго?» (timedelta).
Давайте рассмотрим две даты, которые мы можем представить с помощью двух объектов datetime
. Вычитание одной даты из другой создает объект timedelta
, представляющий временной интервал между датами:
import datetime first_date = datetime.datetime(year=2024, month=1, day=1) second_date = datetime.datetime(year=2024, month=5, day=27) interval = second_date - first_date print(interval) # Вывод: # 147 days, 0:00:00
Результат показывает, что две даты находятся на расстоянии ровно 147 дней друг от друга. В следующем примере мы используем дату и время выполнения кода, вызывая datetime.datetime.now()
:
first_date = datetime.datetime(year=2024, month=1, day=1) second_date = datetime.datetime.now() interval = second_date - first_date print(second_date) print(interval) # Вывод: # 2024-05-28 08:32:44.871646 # 148 days, 8:32:44.871646
Теперь объект timedelta
показывает время, прошедшее между началом 2024 года и датой и временем выполнения нашего кода.
Создание объектов timedelta
В предыдущем разделе мы создали объект timedelta
из двух объектов datetime
. Но мы также можем создать временной интервал напрямую, вызвав конструктор timedelta()
:
interval = datetime.timedelta(days=10, seconds=3600) print(interval) # Вывод: # 10 days, 1:00:00
Интервал составляет десять дней и один час. При создании экземпляра timedelta
можно использовать и другие единицы времени:
interval = datetime.timedelta(weeks=1, days=3, hours=1) print(interval) # Вывод: # 10 days, 1:00:00
При вызове timedelta()
допустимы любые из следующих единиц времени:
- weeks (недели)
- days (дни)
- hours (часы)
- minutes (минуты)
- seconds (секунды)
- milliseconds (миллисекунды)
- microseconds (микросекунды)
Базовая арифметика с timedelta
С объектами timedelta
также можно выполнять арифметические операции. Рассмотрим следующие три объекта datetime
, представляющие даты выхода Python 1.0, Python 2.0 и Python 3.0. Вычитание объектов datetime
друг из друга создает объект timedelta
:
release_date_python_1 = datetime.datetime(year=1991, month=2, day=20) release_date_python_2 = datetime.datetime(year=2000, month=10, day=16) release_date_python_3 = datetime.datetime(year=2008, month=12, day=3) time_between_1_and_2 = release_date_python_2 - release_date_python_1 time_between_2_and_3 = release_date_python_3 - release_date_python_2 print(time_between_1_and_2) print(time_between_2_and_3) # Вывод: # 3526 days, 0:00:00 # 2970 days, 0:00:00
Результат показывает количество дней между релизами Python 1.0 и 2.0 и между релизами Python 2.0 и 3.0. Временные интервалы представляют собой объекты timedelta
.
Также можно выполнять сложение и вычитание между объектами timedelta
и объектами datetime
. Давайте к release_date_python_3
прибавим timedelta
с days=100
:
print(release_date_python_3 + datetime.timedelta(days=100)) # Вывод: # 2009-03-13 00:00:00
Python 3.0 был выпущен 3 декабря 2008 года. Добавив сто дней к этой дате, мы получим 13 марта 2009 года.
Однако мы также можем выполнять арифметические операции непосредственно с объектами timedelta
:
print("Difference between gap 1 and gap 2") print(time_between_1_and_2 - time_between_2_and_3) print("Sum of gap 1 and gap 2") print(time_between_1_and_2 + time_between_2_and_3)
Результат:
Difference between gap 1 and gap 2 556 days, 0:00:00 Sum of gap 1 and gap 2 6496 days, 0:00:00
Вывод подтверждает, что объекты timedelta
можно вычитать и складывать. Также возможны умножение и деление:
print("Multiply time interval by 3:") print(time_between_1_and_2 * 3) print("Divide time interval by 3:") print(time_between_1_and_2 / 3)
Результат:
Multiply time interval by 3: 10578 days, 0:00:00 Divide time interval by 3: 1175 days, 8:00:00
Еще объекты timedelta можно сравнивать:
print("Check if gap 1 is greater than gap 2") print(time_between_1_and_2 > time_between_2_and_3) # Вывод: # True
Вывод подтверждает, что интервал между датами выпуска Python 1.0 и Python 2.0 больше, чем интервал между Python 2.0 и Python 3.0.
Ключевые атрибуты и методы timedelta
Объект timedelta
представляет временной интервал, храня количество дней, секунд и микросекунд. Эти три единицы – единственные единицы времени, представленные атрибутами в классе timedelta
:
interval = datetime.timedelta( weeks=1, hours=10, minutes=22, milliseconds=1042, ) print(f"{interval = }") print(f"{interval.days = }") print(f"{interval.seconds = }") print(f"{interval.microseconds = }")
Результат:
interval = datetime.timedelta(days=7, seconds=37321, microseconds=42000) interval.days = 7 interval.seconds = 37321 interval.microseconds = 42000
Несмотря на то, что при вызове timedelta()
в качестве аргументов можно передавать недели, часы, минуты и миллисекунды (weeks, hours, minutes и milliseconds), конструктор преобразует эти единицы в дни, секунды и микросекунды. Вызовы print()
включают f-строки со знаком равенства =
для отображения имени переменной и ее значения.
Еще одним полезным инструментом класса timedelta
является метод total_seconds()
. Он возвращает общий временной интервал в секундах:
print("Total time interval in seconds:") print(interval.total_seconds()) # Вывод: # Total time interval in seconds: # 642121.042
Весь временной интервал в секундах – не то же самое, что значение .seconds
, которое показывает только секундную составляющую интервала без учета дней и микросекунд.
Мы можем использовать значение, возвращаемое функцией .total_seconds()
, для преобразования временного интервала в любую другую единицу:
print("Total time interval in days:") print(interval.total_seconds() / 3600 / 24) # Вывод: # Total time interval in days: # 7.431956504629629
Вывод показывает временной интервал в днях, поскольку значение, возвращаемое функцией .total_seconds()
, делится на количество секунд в часе и количество часов в сутках.
Пример использования timedelta
Давайте рассмотрим пример. Интернет-магазин компании, продающей книги по Python, регистрирует все продажи. Вот данные по одному покупателю:
data = { "customer_id": 3542, "sales": [ {"date": "2024-04-21T13:23:45", "price": 24.99, "quantity": 1}, {"date": "2024-02-13T10:54:12", "price": 24.99, "quantity": 2}, {"date": "2024-01-08T20:32:24", "price": 18.99, "quantity": 1}, ], }
Нам нужно рассчитать разницу во времени между первым и последним заказами покупателя. В списке, содержащем все продажи, заказы всегда располагаются в хронологическом порядке.
Первым делом нам нужно извлечь даты из этой вложенной структуры и преобразовать их в объекты datetime
. К счастью, временные метки имеют стандартный формат ISO 8601 (YYYY-MM-DDTHH:MM:SS), поэтому мы можем использовать удобный метод fromisoformat()
:
sales = data["sales"] dates = [] for item in sales: date = datetime.datetime.fromisoformat(item["date"]) dates.append(date) print(dates) # Вывод: # [datetime.datetime(2024, 4, 21, 13, 23, 45), datetime.datetime(2024, 2, 13, 10, 54, 12), datetime.datetime(2024, 1, 8, 20, 32, 24)]
Список dates
содержит объекты datetime
с датами каждого заказа. Наконец, мы можем вычислить временной интервал между первым и последним заказом:
time_span = dates[0] - dates[-1] print(time_span) print(time_span.days) # Вывод: # 103 days, 16:51:21 # 103
Разница между первой и последней датами дает нам объект timedelta
. Код отображает time_span
, который показывает количество дней, часов, минут и секунд. Мы также выводим time_span.days
, чтобы показать только целое число дней.
Краткие советы по использованию timedelta
Давайте рассмотрим несколько моментов, которые следует иметь в виду при использовании timedelta
в Python:
1. При вызове timedelta()
лучше использовать именованные аргументы, чтобы избежать ошибок с единицами измерения:
interval = datetime.timedelta(weeks=1, days=3, hours=1, milliseconds=1354)
2. При нахождении временного интервала между двумя датами в разных часовых поясах timedelta
перед вычислением разницы преобразует даты в даты UTC:
import zoneinfo some_date = datetime.datetime.fromisoformat("2024-01-01T00:00:00") some_date_lon = some_date.replace(tzinfo=zoneinfo.ZoneInfo("Europe/London")) some_date_nyc = some_date.replace(tzinfo=zoneinfo.ZoneInfo("America/New_York")) print(some_date_lon) print(some_date_nyc) print(some_date_nyc - some_date_lon)
Результат:
2024-01-01 00:00:00+00:00 2024-01-01 00:00:00-05:00 5:00:00
Дата в some_date
показывает начало нового года. Это наивный объект datetime
, поскольку в нем нет информации о часовом поясе. А вот some_date_lon
и some_date_nyc
– это продуманные объекты datetime
, поскольку они представляют начало нового года в Лондоне и Нью-Йорке соответственно.
Timedelta, полученная путем вычитания двух объектов с известным временем, показывает пятичасовой интервал, что является разницей во времени UTC.
3. В timedelta
не учитывается переход на летнее время.
nyc = zoneinfo.ZoneInfo("America/New_York") first_time = datetime.datetime.strptime("2024-03-10 1:00am", "%Y-%m-%d %I:%M%p") first_time = first_time.replace(tzinfo=nyc) second_time = datetime.datetime.strptime("2024-03-10 3:00am", "%Y-%m-%d %I:%M%p") second_time = second_time.replace(tzinfo=nyc) time_difference = second_time - first_time print("Time difference between the first and second time:") print(time_difference) print("Checking the DST status of the first and second time:") print(f"{first_time.dst() = }") print(f"{second_time.dst() = }")
Результат:
Time difference between the first and second time: 2:00:00 Checking the DST status of the first and second time: first_time.dst() = datetime.timedelta(0) second_time.dst() = datetime.timedelta(seconds=3600)
Два времени представляют 1:00 и 3:00 утра 3 марта 2024 года в Нью-Йорке. Переход на летнее время начался в 2:00 в тот же день, когда часы перевели на 3:00. Разница между этими двумя временами дает timedelta
, равную двум часам, хотя из-за перехода на летнее время между этими временными точками прошел только один час.
Если нам нужно реальное количество прошедшего времени, мы можем применить конвертацию в UTC:
first_time_utc = first_time.astimezone(zoneinfo.ZoneInfo("UTC")) second_time_utc = second_time.astimezone(zoneinfo.ZoneInfo("UTC")) time_difference_utc = second_time_utc - first_time_utc print("Actual time difference between the first and second time:") print(time_difference_utc)
Результат:
Actual time difference between the first and second time: 1:00:00
Преобразование в UTC перед вычитанием объектов datetime
дает фактическое время между двумя объектами datetime
.
Заключение
Класс timedelta
в Python предлагает простые методы для работы с временными интервалами, облегчая работу с периодами времени в различных единицах. Мы рассмотрели, как создавать объекты timedelta
и выполнять с ними арифметические операции, включая сложение, вычитание, умножение и деление.
Перевод статьи «Python timedelta: Working With Time Intervals in Python».
Всем хорошего настроения!!!!!