Преобразование строк в дату и время в Python

Введение

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

Один из самых распространенных источников дата и время в строковом формате — это REST API, которые возвращают независимые строки, которые затем можно преобразовать в другие форматы.

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

В этом руководстве мы рассмотрим, как преобразовать строковую дату/время в datetime объект в Python, используя встроенный datetime модуль, но и сторонние модули, такие как dateutil, arrow и Maya, учитывающая часовые пояса.

Преобразование строк с использованием даты и времени

Ассоциация Дата и время модуль состоит из трех разных типов объектов: date, timeкачества datetime, date объект содержит дату, time держит время и datetime держит и дату и время!

import datetime
print(f'Current date/time: {datetime.datetime.now()}')

Запуск этого кода приведет к:

Current date/time: 2022-12-01 10:27:03.929149

Если пользовательское форматирование не задано, используется строковый формат по умолчанию, т. е. формат «2022-12-01 10:27:03.929149» находится в ISO 8601 формат (ГГГГ-ММ-ДДЧЧ:ММ:СС.мммммм). Если наша входная строка для создания datetime объект находится в том же формате ISO 8601, или если вы заранее знаете формат, который вы получите, мы можем легко преобразовать его в datetime объект:

import datetime

date_time_str = '2022-12-01 10:27:03.929149'

date_time_obj = datetime.datetime.strptime(date_time_str, '%Y-%m-%d %H:%M:%S.%f')

print('Date:', date_time_obj.date())
print('Time:', date_time_obj.time())
print('Date-time:', date_time_obj)

Запустив его, вы напечатаете дату, время и дату-время:

Date: 2022-12-01
Time: 10:27:03.929149
Date-time: 2022-12-01 10:27:03.929149

Здесь мы используем strptime() метод, который принимает два аргумента:

  • Дата в строковом формате
  • Формат первого аргумента

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

В нашем примере "2022-12-01 10:27:03.929149" это входная строка и "%Y-%m-%d %H:%M:%S.%f" это формат нашей строки даты. Возвращенный datetime значение хранится как date_time_obj.

Так как это datetime объект, мы можем назвать date() и time() методы непосредственно на нем. Как видно из вывода, он печатает часть входной строки «дата» и «время»!

Токены формата

Стоит уделить время, чтобы понять форматировать токены - "%Y-%m-%d %H:%M:%S.%f" из ранее.

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

  • %Y: Год (4 цифры)
  • %m: Месяц
  • %d: День месяца
  • %H: Час (24 часа)
  • %M: Минуты
  • %S: Секунды
  • %f: микросекунды

Примечание: Ожидается, что все эти токены, кроме года, будут дополнены нулями (т. е. август — это 8-й месяц, и 08).

Использование токенов формата strptime() для преобразования строки в другой формат даты и времени

Если формат строки известен, ее можно легко преобразовать в datetime объект, использующий strptime(). Давайте рассмотрим нетривиальный пример перевода из одного формата в другой:

import datetime

date_time_str = 'Jul 17 2022 9:20AM'
date_time_obj = datetime.datetime.strptime(date_time_str, '%b %d %Y %I:%M%p')

print('Date:', date_time_obj.date())
print('Time:', date_time_obj.time())
print('Date-time:', date_time_obj)

Входная строка была одного формата — «17 июля 2022, 9:20». Зная этот формат, мы сопоставили составные элементы с форматом ISO 8601 и преобразовали его в datetime объект:

Date: 2022-07-17
Time: 09:20:00
Date-time: 2022-07-17 09:20:00

Вот краткий список распространенных значений даты и времени в строковом формате и соответствующих им форматов для strptime():

"Jun 28 2018 at 7:40AM" -> "%b %d %Y at %I:%M%p"
"September 18, 2017, 22:19:55" -> "%B %d, %Y, %H:%M:%S"
"Sun,05/12/99,12:30PM" -> "%a,%d/%m/%y,%I:%M%p"
"Mon, 21 March, 2015" -> "%a, %d %B, %Y"
"2018-03-12T10:12:45Z" -> "%Y-%m-%dT%H:%M:%SZ"

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

Преобразование строки в дату и время с часовыми поясами

Обработка даты и времени становится более сложной при работе с часовыми поясами. Все приведенные выше примеры до сих пор наивны для часового пояса. Они известны как наивные объекты даты и времени.

Однако datetime объекты содержат поле именно для хранения данных, связанных с часовым поясом – tzinfo:

import datetime as dt
dtime = dt.datetime.now()

print(dtime) 
print(dtime.tzinfo) 

Ассоциация tzinfo поле предназначено для datetime.timezone объект, обозначающий информацию о часовом поясе. Это None по умолчанию и означает, что объект datetime не зависит от часового пояса. Очень распространенная внешняя библиотека для обработки часовых поясов: pytz. Вы можете установить ПыТз объекты как tzinfo поле тоже.

Если у вас его еще нет – установите его через:

$ pip install pytz

Используя PyTz, мы можем создать якорь для даты и времени с учетом часового пояса, например UTC:

import datetime as dt
import pytz

dtime = dt.datetime.now(pytz.utc)

print(dtime)
print(dtime.tzinfo)

Вывод:

2022-12-01 02:07:41.960920+00:00
UTC

Сейчас уже не 11 утра, а 2 часа ночи, потому что мы перевели часовой пояс на несколько часов назад! Этот меняет часовой пояс даты и времени.

+00:00 — это разница между отображаемым временем и временем UTC в качестве глобальной привязки координации. Мы установили время в формате UTC, поэтому смещение равно 00:00. Это объект с учетом часового пояса.

Точно так же мы можем переключать одну и ту же интерпретацию даты и времени между часовыми поясами. Давайте преобразуем строку, например «2022-06-29 17:08:00», в дату и время, а затем локализуются в часовой пояс America/New_York:

import datetime as dt
import pytz

date_time_str = '2022-06-29 17:08:00'
date_time_obj = dt.datetime.strptime(date_time_str, '%Y-%m-%d %H:%M:%S')

timezone = pytz.timezone('America/New_York')
timezone_date_time_obj = timezone.localize(date_time_obj)

print(timezone_date_time_obj)
print(timezone_date_time_obj.tzinfo)

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

Мы получаем то же самое значение даты и времени, компенсируется -04: 00 по сравнению со временем UTC:

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

17:08 в Токио не тот же момент времени, что и 17:08 в Нью-Йорке. 17:08 в Токио — 3:08 в Нью-Йорке.

Как найти все коды/псевдонимы часовых поясов?

Чтобы найти все доступные часовые пояса, проверьте all_timezones поле, которое представляет собой список всех доступных часовых поясов:

print(f'There are {len(pytz.all_timezones)} timezones in PyTzn')
for time_zone in pytz.all_timezones:
   print(time_zone)

Ознакомьтесь с нашим практическим руководством по изучению Git с рекомендациями, принятыми в отрасли стандартами и прилагаемой памяткой. Перестаньте гуглить команды Git и на самом деле изучить это!

There are 594 timezones in PyTz

Africa/Abidjan
Africa/Accra
Africa/Addis_Ababa
Africa/Algiers
Africa/Asmara
Africa/Asmera
...

Изменить часовой пояс Datetime

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

Это отличается от локализации, поскольку локализация представляет другой момент времени, но преобразование часового пояса объекта представляет тот же момент времени через другую линзу:

import datetime as dt
import pytz

timezone_nw = pytz.timezone('America/New_York')
nw_datetime_obj = dt.datetime.now(timezone_nw)

timezone_london = pytz.timezone('Europe/London')
london_datetime_obj = nw_datetime_obj.astimezone(timezone_london)


print('America/New_York:', nw_datetime_obj)
print('Europe/London:', london_datetime_obj)

Во-первых, мы создали один объект datetime с текущим временем и установили его в качестве часового пояса «Америка/Нью-Йорк». Затем с помощью astimezone() метод, мы преобразовали этот datetime в часовой пояс «Европа/Лондон». Оба datetimes будет печатать разные значения, используя смещение UTC в качестве ссылки между ними:

America/New_York: 2022-11-30 21:24:30.123400-05:00
Europe/London: 2022-12-01 02:24:30.123400+00:00

2:24 на следующий день в Лондоне is тот же момент времени, что и 21:24 предыдущего дня в Нью-Йорке так как Лондон на 5 часов впереди.

Как и ожидалось, дата-время отличается, поскольку они разнятся примерно на 5 часов.

Преобразование строки в дату и время с использованием сторонних библиотек

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

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

В некоторых случаях эти сторонние библиотеки также имеют лучшую встроенную поддержку для манипулирования и сравнения даты и времени, а некоторые даже имеют встроенные часовые пояса, поэтому вам не нужно включать дополнительный пакет PyTz.

Давайте рассмотрим некоторые из этих библиотек в следующих разделах.

Преобразование строки в Datetime с помощью dateutil

Ассоциация модуль dateutil является продолжением datetime модуль. Одним из преимуществ является то, что нам не нужно передавать какой-либо код синтаксического анализа для анализа строки!

Чтобы автоматически преобразовать строку в дату и время без токена формата, используя Python dateutil:

from dateutil.parser import parse
datetime = parse('2018-06-29 22:21:41')

print(datetime)

Эта parse функция будет автоматически анализировать строку! Вам не нужно включать какую-либо строку формата. Давайте попробуем разобрать разные типы строк, используя dateutil:

from dateutil.parser import parse

date_array = [
    '2018-06-29 08:15:27.243860',
    'Jun 28 2018 7:40AM',
    'Jun 28 2018 at 7:40AM',
    'September 18, 2017, 22:19:55',
    'Sun, 05/12/1999, 12:30PM',
    'Mon, 21 March, 2015',
    '2018-03-12T10:12:45Z',
    '2018-06-29 17:08:00.586525+00:00',
    '2018-06-29 17:08:00.586525+05:00',
    'Tuesday , 6th September, 2017 at 4:30pm'
]

for date in date_array:
    print('Parsing: ' + date)
    dt = parse(date)
    print(dt.date())
    print(dt.time())
    print(dt.tzinfo)
    print('n')

Вывод:

Parsing: 2018-06-29 08:15:27.243860
2018-06-29
08:15:27.243860
None

Parsing: Jun 28 2018 7:40AM
2018-06-28
07:40:00
None

Parsing: Jun 28 2018 at 7:40AM
2018-06-28
07:40:00
None

Parsing: September 18, 2017, 22:19:55
2017-09-18
22:19:55
None

Parsing: Sun, 05/12/1999, 12:30PM
1999-05-12
12:30:00
None

Parsing: Mon, 21 March, 2015
2015-03-21
00:00:00
None

Parsing: 2018-03-12T10:12:45Z
2018-03-12
10:12:45
tzutc()

Parsing: 2018-06-29 17:08:00.586525+00:00
2018-06-29
17:08:00.586525
tzutc()

Parsing: 2018-06-29 17:08:00.586525+05:00
2018-06-29
17:08:00.586525
tzoffset(None, 18000)

Parsing: Tuesday , 6th September, 2017 at 4:30pm
2017-09-06
16:30:00
None

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

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

Преобразование строки в дату и время с помощью Maya

Maya также позволяет очень легко анализировать строку и изменять часовые пояса. Чтобы легко преобразовать строку с помощью Maya Python:

import maya

dt = maya.parse('2018-04-29T17:45:25Z').datetime()
print(dt.date())
print(dt.time())
print(dt.tzinfo)

Вывод:

2018-04-29
17:45:25
UTC

Для преобразования времени в другой часовой пояс:

import maya

dt = maya.parse('2018-04-29T17:45:25Z').datetime(to_timezone='America/New_York', naive=False)
print(dt.date())
print(dt.time())
print(dt.tzinfo)

Вывод:

2018-04-29
13:45:25
America/New_York

Теперь это не легко использовать? давайте попробуем maya с тем же набором строк, который мы использовали с dateutil:

import maya

date_array = [
    '2018-06-29 08:15:27.243860',
    'Jun 28 2018 7:40AM',
    'Jun 28 2018 at 7:40AM',
    'September 18, 2017, 22:19:55',
    'Sun, 05/12/1999, 12:30PM',
    'Mon, 21 March, 2015',
    '2018-03-12T10:12:45Z',
    '2018-06-29 17:08:00.586525+00:00',
    '2018-06-29 17:08:00.586525+05:00',
    'Tuesday , 6th September, 2017 at 4:30pm'
]

for date in date_array:
    print('Parsing: ' + date)
    dt = maya.parse(date).datetime()
    print(dt)
    
    
    
    

Вывод:

Parsing: 2018-06-29 08:15:27.243860
2018-06-29 08:15:27.243860+00:00

Parsing: Jun 28 2018 7:40AM
2018-06-28 07:40:00+00:00

Parsing: Jun 28 2018 at 7:40AM
2018-06-28 07:40:00+00:00

Parsing: September 18, 2017, 22:19:55
2017-09-18 22:19:55+00:00

Parsing: Sun, 05/12/1999, 12:30PM
1999-05-12 12:30:00+00:00

Parsing: Mon, 21 March, 2015
2015-03-21 00:00:00+00:00

Parsing: 2018-03-12T10:12:45Z
2018-03-12 10:12:45+00:00

Parsing: 2018-06-29 17:08:00.586525+00:00
2018-06-29 17:08:00.586525+00:00

Parsing: 2018-06-29 17:08:00.586525+05:00
2018-06-29 12:08:00.586525+00:00

Parsing: Tuesday , 6th September, 2017 at 4:30pm
2017-09-06 16:30:00+00:00

Как видите, все форматы даты были успешно проанализированы!

Если мы не предоставим информацию о часовом поясе, он автоматически преобразует ее в UTC. Итак, важно отметить, что мы должен обеспечить to_timezone и naive параметры, если время не в формате UTC.

Преобразование строки в дату и время с помощью стрелки

Arrow — еще одна библиотека для работы с датой и временем в Python. И как прежде с maya, он также автоматически определяет формат даты и времени. После интерпретации он возвращает Python datetime объект из arrow объект.

Чтобы легко преобразовать строку в дату и время, используя Python arrow:

import arrow

dt = arrow.get('2018-04-29T17:45:25Z')
print(dt.date())
print(dt.time())
print(dt.tzinfo)

Вывод:

2018-04-29
17:45:25
tzutc()

А вот как можно использовать arrow для преобразования часовых поясов с помощью to() Метод:

import arrow

dt = arrow.get('2018-04-29T17:45:25Z').to('America/New_York')
print(dt)
print(dt.date())
print(dt.time())

Вывод:

2018-04-29T13:45:25-04:00
2018-04-29
13:45:25

Как видите, строка даты и времени преобразуется в регион «Америка/Нью-Йорк».

Теперь давайте снова используем тот же набор строк, который мы использовали выше:

import arrow

date_array = [
    '2018-06-29 08:15:27.243860',
    
    
    
    
    
    '2018-03-12T10:12:45Z',
    '2018-06-29 17:08:00.586525+00:00',
    '2018-06-29 17:08:00.586525+05:00',
    
]

for date in date_array:
    dt = arrow.get(date)
    print('Parsing: ' + date)
    print(dt)
    
    
    
    

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

Parsing: 2018-06-29 08:15:27.243860
2018-06-29T08:15:27.243860+00:00

Parsing: 2018-03-12T10:12:45Z
2018-03-12T10:12:45+00:00

Parsing: 2018-06-29 17:08:00.586525+00:00
2018-06-29T17:08:00.586525+00:00

Parsing: 2018-06-29 17:08:00.586525+05:00
2018-06-29T17:08:00.586525+05:00

Чтобы правильно проанализировать закомментированные строки даты и времени, вам необходимо передать соответствующий форматировать токены чтобы дать библиотеке подсказки о том, как ее анализировать.

Заключение

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

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

Еще одна проблема, с которой мы сталкиваемся, связана с часовыми поясами. Лучший способ справиться с ними — всегда хранить время в вашей базе данных в формате UTC, а затем при необходимости преобразовывать его в локальный часовой пояс пользователя.

Эти библиотеки хороши не только для синтаксического анализа строк, но и для множества различных операций, связанных с датой и временем. Я бы посоветовал вам просмотреть документы, чтобы подробно изучить функциональные возможности.

Отметка времени:

Больше от Стекабьюс