Работа с датами и временем в Python

Модуль datetime

У нас есть описание модуля time, продолжим изучать работу с временем.

Datetime — важный элемент любой программы, написанной на Python. Этот модуль позволяет управлять датами и временем, представляя их в таком виде, в котором пользователи смогут их понимать.

datetime включает различные компоненты. Так, он состоит из объектов следующих типов:

  • date — хранит дату
  • time — хранит время
  • datetime — хранит дату и время

Класс date
Для работы с датами воспользуемся классом date, который определен в модуле datetime. Для создания объекта date мы можем использовать конструктор date, который последовательно принимает три параметра: год, месяц и день.

date(year, month, day)

Например, создадим какую-либо дату:

import datetime

yesterday = datetime.date(2017,5, 2)
print(yesterday) # 2017-05-02

Если необходимо получить текущую дату, то можно воспользоваться методом today():

from datetime import date

today = date.today()
print(today) # 2017-05-03
print(“{}.{}.{}”.format(today.day, today.month, today.year)) # 2.5.2017

С помощью свойств day, month, year можно получить соответственно день, месяц и год/

Класс time
За работу с временем отвечает класс time. Используя его конструктор, можно создать объект времени:

time([hour] [, min] [, sec] [, microsec])

Конструктор последовательно принимает часы, минуты, секунды и микросекунды. Все параметры необязательные, и если мы какой-то параметр не передадим, то соответствующее значение будет инициализироваться нулем.

from datetime import time

current_time = time()
print(current_time) # 00:00:00

current_time = time(16, 25)
print(current_time) # 16:25:00

current_time = time(16, 25, 45)
print(current_time) # 16:25:45

Класс datetime
Класс datetime из одноименного модуля объединяет возможности работы с датой и временем. Для создания объекта datetime можно использовать следующий конструктор:

datetime(year, month, day [, hour] [, min] [, sec] [, microsec])

Первые три параметра, представляющие год, месяц и день, являются обязательными. Остальные необязательные, и если мы не укажем для них значения, то по умолчанию они инициализируются нулем.

from datetime import datetime

deadline = datetime(2017, 5, 10)
print(deadline) # 2017-05-10 00:00:00

deadline = datetime(2017, 5, 10, 4, 30)
print(deadline) # 2017-05-10 04:30:00

Для получения текущих даты и времени можно вызвать метод now():

from datetime import datetime

now = datetime.now()
print(now) # 2017-05-03 11:18:56.239443

print(“{}.{}.{} {}:{}”.format(now.day, now.month, now.year, now.hour, now.minute)) # 3.5.2017 11:21

print(now.date())
print(now.time())

С помощью свойств day, month, year, hour, minute, second можно получить отдельные значения даты и времени. А через методы date() и time() можно получить отдельно дату и время соответственно.

Преобразование из строки в дату
Из функциональности класса datetime следует отметить метод strptime(), который позволяет распарсить строку и преобразовать ее в дату. Этот метод принимает два параметра:

strptime(str, format)

Первый параметр str представляет строковое определение даты и времени, а второй параметр – формат, который определяет, как различные части даты и времени расположены в этой строке.

Для определения формата мы можем использовать следующие коды:

%d: день месяца в виде числа

%m: порядковый номер месяца

%y: год в виде 2-х чисел

%Y: год в виде 4-х чисел

%H: час в 24-х часовом формате

%M: минута

%S: секунда

Применим различные форматы:

from datetime import datetime
deadline = datetime.strptime(“22/05/2017”, “%d/%m/%Y”)
print(deadline) # 2017-05-22 00:00:00

deadline = datetime.strptime(“22/05/2017 12:30”, “%d/%m/%Y %H:%M”)
print(deadline) # 2017-05-22 12:30:00

deadline = datetime.strptime(“05-22-2017 12:30”, “%m-%d-%Y %H:%M”)
print(deadline) # 2017-05-22 12:30:00

С помощью модуля Python это сделать очень просто. Сначала нужно импортировать класс datetime из модуля datetime, после чего создать объект datetime. Модуль предоставляет метод now(), который возвращает текущие дату и время с учетом локальных настроек.


import datetime dt_now = datetime.datetime.now() print(dt_now)

А вот результат:

2020-11-14 15:43:32.249588

Получить текущую дату в Python

Класс date можно использовать для получения или изменения объектов даты. Например, для получения текущей с учетом настроек подойдет следующее:


from datetime import date current_date = date.today() print(current_date)

Результат:

2020-11-14

Текущая дата — 2020-11-14 в формате год-месяц-день соответственно.

Получить текущее время

Для получения текущего локального времени сперва нужно получить текущие дату и время, а затем достать из этого объекта только время с помощью метода time():


import datetime current_date_time = datetime.datetime.now() current_time = current_date_time.time() print(current_time)

Результат:

15:51:05.627643

Компоненты datetime в Python

Модуль datetime в Python может использоваться для получения разных версий времени. Для этого нужно ознакомиться с атрибутами модуля. Используем для этого функцию dir().


import datetime attr = dir(datetime) print(attr) # ['MAXYEAR', 'MINYEAR', '__doc__', '__name__', '__package__', 'date', 'datetime', # 'datetime_CAPI', 'time', 'timedelta', 'tzinfo']

В этом руководстве речь пойдет о следующих элементах:

  • date — объекты даты
  • datetime — объекты даты и времени
  • time — объекты времени
  • timedelta — этот атрибут покрывает интервалы и используется для определения прошлых или будущих событий
  • Tzinfo — этот атрибут отвечает за часовые пояса

Как создавать объекты даты и времени

Для создания объекта времени используется класс time из модуля datetime в Python. Синтаксис следующий: datetime.time(hour, minutes, seconds).

В этом примере создается объект времени представленный следующим образом (8, 48, 45).


import datetime timeobj= datetime.time(8,48,45) print(timeobj)

Результат такой:

08:48:45

Сначала импортируется модуль datetime. После этого создается экземпляр класса (объект time). Затем ему присваивается значение datetime.time(8, 48, 45), где параметры 8, 48 и 45 представляют собой часы, минуты и секунды соответственно.

Для создания объекта даты нужно передать дату с использованием следующего синтаксиса:

datetime.datetime(year,month,day))

Такой пример:


import datetime date_obj = datetime.datetime(2020,10,17) print(date_obj)

Вернет вот такой результат:

2020-10-17 00:00:00

Timedelta

timedelta представляет длительность (даты или времени). Модуль datetime включает атрибут timedelta(), который используется для управления датой в Python. Объект timedelta выглядит следующим образом:


td_object =timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0) td_object datetime.timedelta(0)

Все аргументы опциональные и их значения по умолчанию равно 0. Они могут быть целыми или числами с плавающей точкой, как положительными, так и отрицательными. Благодаря этому можно выполнять математические операции, такие как сложение, вычитание и умножение.

Как вычислить разницу для двух дат

Посмотрим на несколько примеров вычисления разницы во времени. Предположим, есть два объекта datetime:

first_date = date(2020, 10, 2)

second_date = date(2020, 10, 30)

Для получения разницы нужно лишь вычесть значение одного объекта из второго:


from datetime import date first_date = date(2020, 10, 2) second_date = date(2020, 10, 30) delta = second_date - first_date print(delta)

Результат:

28 days,0:00:00

Таким образом между 2 и 30 октября 2020 года 28 дней.

Как вычислить разницу двух объектов datetime.time

С помощью timedelta нельзя выполнять манипуляции над объектами time. Например:


from datetime import datetime, timedelta current_datetime = datetime.now() current_time = current_datetime.time() print("Текущее время:", current_time) tm_after_1_hr = current_time + timedelta(hours=1) print(tm_after_1_hr)

Такой код вернет следующую ошибку:

Traceback (most recent call last): File “C:\Users\alex\AppData\Local\Programs\Python\Python38\sg_verify.py”, line 6, in tm_after_1_hr = current_time + timedelta(hours=1) TypeError: unsupported operand type(s) for +: ‘datetime.time’ and ‘datetime.timedelta’

Как получать прошлые и будущие даты с помощью timedelta

Поскольку timedelta — это длительность, то для получения прошлой или будущей даты нужно добавить объект timedelta к существующему или вычесть из него же. Вот пример нескольких уравнений, где n — это целое число, представляющее количество дней:


import datetime current_date = datetime.datetime.today() past_date = datetime.datetime.today() – datetime.timedelta(days=n) future_date = datetime.datetime.today() – datetime.timedelta(days=n)

Если нужно, например, получить дату за прошлые две недели, то достаточно вычесть 14 дней из текущей даты:


import datetime past_date = datetime.datetime.today() - datetime.timedelta(days=14) print(past_date)

Результат:

2020-10-31 16:12:09.142258

Предположим, вы задумали практиковать определенный навык в течение 21 дня. Для получения будущей даты нужно добавить 21 день к текущей дате:


import datetime future_date = datetime.datetime.today() + datetime.timedelta(days=21) print(future_date)

Результат:

2020-12-05 16:14:09.718325

Другие арифметические операции с timedelta

Значения даты и времени могут сравниваться для определения того, какая из них была раньше или позже. Например:


import datetime now = datetime.time(9, 31, 0) next_hour = datetime.time(10, 31, 0) print('now < next_hour:', now < next_hour) today = datetime.date.today() next_week = datetime.date.today() + datetime.timedelta(days=7) print('today > next_week:', today > next_week)

Результат:

now < next_hour: True

today > next_week: False

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

Пока что мы работали с datetime без учета часовых поясов и летнего времени. Но прежде чем переходить к следующим пунктам, нужно разобраться с разницей в абсолютных (naive) и относительных (aware) датах.

Абсолютные даты не содержат информацию, которая бы могла определить часовой пояс или летнее время. Однако с такими намного проще работать.

Относительные же содержат достаточно информации для определения часового пояса или отслеживания изменений из-за летнего времени.

Разница между DST, GMT и UTC

  1. GMT
    Официальный часовой пояс, используемый в некоторых странах Европы и Африки. Он может быть представлен как в 24, так и в 12-часовом форматах. GMT используется для того, чтобы задавать местное время. Например, местное время для Берлина 2020–10–17 09:40:33.614581+02:00 GMT. Для Найроби же это — 2020–10–17 10:40:33.592608+03:00 GMT.
  2. DST (летнее время)
    Страны, которые переходят на летнее время, делают это для того, чтобы дневное время длилось как можно дольше. Во время летнего времени они переводят стрелки своих часов на час вперед и возвращаются обратно осенью.
  3. UTC (всемирное координированное время)
    Временной стандарт для часовых поясов во всем мире. Он позволяет синхронизировать время во всем мире и служит отправной точкой для остальных.

Как работать с часовыми поясами

Рассмотрим, как создать простой относительный объект datetime:


import datetime dt_now = datetime.datetime.utcnow() print(dt_now)

Эта программа возвращает объект с абсолютным значением datetime. Если же нужно сделать его абсолютным, то нужно явно указать часовой пояс. Как это сделать? В библиотеке datetime в Python нет модуля для работы с часовыми поясами. Для этого нужно использовать другие библиотеки. Одна из таких — pytz.

Предположим, нужно получить текущее время для Найроби. Для этого нужно использовать конкретный часовой пояс. Для начала можно с помощью pytz получить все существующие часовые пояса.


import pytz pytz.all_timezones

Вот некоторые из них:

[‘Africa/Abidjan’, ‘Africa/Accra’, ‘Africa/Addis_Ababa’, ‘Africa/Nairobi’]

Для получения времени в Найроби:


import pytz import datetime tz_nairobi = pytz.timezone("Africa/Nairobi") dt_nairobi =datetime.datetime.now(tz_nairobi) print(dt_nairobi)

Результат:

2020-11-14 17:27:31.141255+03:00

А вот так можно получить время Берлина:


import pytz import datetime tz_berlin = pytz.timezone("Europe/Berlin") dt_berlin =datetime.datetime.now(tz_berlin) print(dt_berlin)

Результат:

2020-11-14 15:28:20.977529+01:00

Здесь можно увидеть разницу в часовых поясах разных городов, хотя сама дата одна и та же.

Конвертация часовых поясов

При конвертации часовых поясов в первую очередь нужно помнить о том, что все атрибуты представлены в UTC. Допустим, нужно конвертировать это значение в America/New_York:


import datetime import pytz timezone_berlin = '2019-06-29 17:08:00' tz_ber_obj = datetime.datetime.strptime(timezone_berlin, '%Y-%m-%d %H:%M:%S') timezone_newyork = pytz.timezone('America/New_York') timezone_newyork_obj = timezone_newyork.localize(tz_ber_obj) print(timezone_newyork_obj) print(timezone_newyork_obj.tzinfo)

Результат:

2019-06-29 17:08:00-04:00 America/New_York

Другие практические примеры

Всегда храните даты в UTC. Вот примеры:


import datetime import pytz time_now = datetime.datetime.now(pytz.utc) print(time_now)

Результат для этого кода — 2020-11-14 14:38:46.462397+00:00, хотя локальное время может быть, например, таким 2020-11-14 16:38:46.462397+00:00. А уже при демонстрации даты пользователю стоит использовать метод localize с местными настройками:


import datetime import pytz now = datetime.datetime.today() now_utc = pytz.utc.localize(now)

Вернет текущее локальное время — 2020-11-14 16:42:38.228528+00:00.

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

strptime() в Python — это метод из модуля datetime. Вот его синтаксис:

dateobj = datetime.strptime(date_string, format)

Аргументы формата необязательные и являются строками. Предположим, нужно извлечь текущие дату и время:


import datetime current_dt = datetime.datetime.now() print(current_dt)

Результат:

2020-11-14 16:50:45.049229

Результат будет в формате ISO 8601, то есть YYYY-MM-DDTHH:MM:SS.mmmmmm — формат по умолчанию, что позволяет получать строки в едином формате.

Таблица форматов:

СимволОписаниеПример
%aДень недели, короткий вариантWed
%AБудний день, полный вариантWednesday
%wДень недели числом 0-6, 0 — воскресенье3
%dДень месяца 01-3131
%bНазвание месяца, короткий вариантDec
%BНазвание месяца, полное названиеDecember
%mМесяц числом 01-1212
%yГод, короткий вариант, без века18
%YГод, полный вариант2018
%HЧас 00-2317
%IЧас 00-1205
%pAM/PMPM
%MМинута 00-5941
%SСекунда 00-5908
%fМикросекунда 000000-999999548513
%zРазница UTC+0100
%ZЧасовой поясCST
%jДень в году 001-366365
%UНеделя числом в году, Воскресенье первый день недели, 00-5352
%WНеделя числом в году, Понедельник первый день недели, 00-5352
%cЛокальная версия даты и времениMon Dec 31 17:41:00 2018
%xЛокальная версия даты12/31/18
%XЛокальная версия времени17:41:00
%%Символ “%”%

import datetime date_string = "11/17/20" date_obj = datetime.datetime.strptime(date_string, '%m/%d/%y') print(date_obj)

Результат:

2020-11-17 00:00:00

Примеры конвертации строки в объект datetime с помощью strptime

Предположим, что есть следующая строка с датой: «11/17/20 15:02:34», и ее нужно конвертировать в объект datetime.


from datetime import datetime datetime_string = "11/17/20 15:02:34" datetime_obj = datetime.strptime(datetime_string, '%m/%d/%y %H:%M:%S') print(datetime_obj)

Результат:

2020-11-17 15:02:34

Даты могут быть записаны в разных форматах. Например, следующие даты отличаются лишь представлением:

  • Friday, November 17, 2020;
  • 11/17/20;
  • 11–17–2020.

Вот как это работает:


from datetime import datetime # создадим даты как строки ds1 = 'Friday, November 17, 2020' ds2 = '11/17/20' ds3 = '11-17-2020' # Конвертируем строки в объекты datetime и сохраним dt1 = datetime.strptime(ds1, '%A, %B %d, %Y') dt2 = datetime.strptime(ds2, '%m/%d/%y') dt3 = datetime.strptime(ds3, '%m-%d-%Y') print(dt1) print(dt2) print(dt3)

Результат будет одинаковым для всех форматов:

2020-11-17 00:00:00

2020-11-17 00:00:00

2020-11-17 00:00:00

Практические примеры

Если строка представлена в формате «Oct 17 2020 9:00PM», то ее можно конвертировать следующим образом:


date_string = 'Oct 17 2020 9:00PM' date_object = datetime.strptime(date_string, '%b %d %Y %I:%M%p') print(date_object)

Результат — 2020-10-17 21:00:00.

Функцию strptime() можно использовать для конвертации строки в объект даты:


from datetime import datetime date_string = '10-17-2020' date_object = datetime.strptime(date_string, '%m-%d-%Y').date() print(type(date_object)) print(date_object)

Результат:

2020-10-17

Как конвертировать объект datetime в строку

Модуль datetime в Python содержит метод strftime(), который делает обратное (то есть, конвертирует объект datetime и time в строки). Вот его синтаксис:

datetime_string = datetime_object.strftime(format_string) time_string = datetime_object.strftime(format_string[,time_object])

Примеры конвертации datetime в строку с помощью strftime()

Предположим, нужно конвертировать текущий объект datetime в строку. Сначала нужно получить представление объекта datetime и вызвать на нем метод strftime().


import datetime current_date = datetime.datetime.now() current_date_string = current_date.strftime('%m/%d/%y %H:%M:%S') print(current_date_string)

Результат — 11/14/20 17:15:03.

Как получить строковое представление даты и времени с помощью функции format()

Пример №1. Конвертация текущей временной метки в объекте datetime в строку в формате «DD-MMM-YYYY (HH:MM:SS:MICROS)»


import datetime dt_obj =datetime.datetime.now() dt_string = dt_obj.strftime("%d-%b-%Y (%H:%M:%S.%f)") print('Текущее время : ', dt_string)

Результат:

Текущее время : 14-Nov-2020 (17:18:09.890960)

Пример №2.

Конвертация текущей временной метки объекта datetime в строку в формате «HH:MM:SS.MICROS – MMM DD YYYY».


import datetime dt_obj =datetime.datetime.now() dt_string = dt_obj.strftime("%H:%M:%S.%f - %b %d %Y") print('Текущее время : ', dt_string)

Результат:

Текущее время : 17:20:28.841390 – Nov 14 2020

Другие datetime-библиотеки в Python

В Python есть и другие библиотеки, которые упрощают процесс манипуляций с объектами datetime. В некоторых из них есть поддержка часовых поясов.

Arrow

Arrow — еще один популярный модуль, который делает более простым процесс создания, управления и форматирования дат и времени. Получить его можно с помощью pip. Для установки достаточно ввести pip install arrow.

Arrow можно использовать для получения текущего времени по аналогии с модулем datetime:


import arrow current_time = arrow.now() print(current_time) print(current_time.to('UTC'))

Результат:

2020-11-14T15:52:58.921198+00:00 2020-11-14T15:52:58.921198+00:00

Maya

Maya упрощает процесс парсинга строк и конвертации часовых поясов. Например:


import maya dt = maya.parse('2019-10-17T17:45:25Z').datetime() print(dt.date()) print(dt) print(dt.time())

Результат:

2019-10-17

2019-10-17 17:45:25+00:00

17:45:25

Dateutil

Dateutil — это мощная библиотека, которая используется для парсинга дат и времени в разных форматах. Вот некоторые примеры.


from dateutil import parser dt_obj = parser.parse('Thu Oct 17 17:10:28 2019') print(dt_obj) dt_obj1=parser.parse('Thursday, 17. October 2019 5:10PM') print(dt_obj1) dt_obj2=parser.parse('10/17/2019 17:10:28') print(dt_obj2) t_obj=parser.parse('10/17/2019') print(t_obj)

Результат:

2019-10-17 17:10:28

2019-10-17 17:10:00

2019-10-17 17:10:28

2010-10-17 00:00:00

Важно, что в этом случае не нужны регулярные выражения при определении формата. Парсер ищет узнаваемые токены и либо возвращает корректный результат, либо выдает ошибку.

Важные нюансы

Вот о чем важно помнить при работе с datetime в Python:

  • Рекомендуется всегда работать с UTC. Это позволяет не думать о часовых поясах, что часто приводит к ошибкам из-за разницы во времени в разных регионах.
  • Дату и время стоит конвертировать в локальную только при выводе пользователю.

Выводы

Есть масса сценариев работы с датой и временем в реальных приложениях. Например:

  • Запланировать работу скрипта на определенное время.
  • Отфильтровать даты.
  • Извлечь дату из определенных API каждый день, в определенное время.
  • Приложения для отслеживания событий, записей, бронирования и так далее.

Особенности, которые заметил:

1. Не допускается прописывать нули перед номерами дней, месяцев, часов и пр.
как собственно и перед простыми целыми числами
yesterday = datetime.date(2021, 07, 01) # не сработает
но в методе strptime() это допускается, т.к. дата и время прописываются как строка

2. классы реализуют проверку корректности введенных дат и времени
(например проконтролирует 29 февраля для високосного года)

Почему вот так не работает?

import datetime
today = datetime.today()
print(today)

В классе datetime нет метода today().
вы должны вызвать класс datetime затем подкласс datetime or date и затем метод.
т.е. today = datetime.date.today() or datetime.datetime.today()