Перетворення рядків на дату й час у Python

Вступ

Дані можуть бути представлені в різних формах, і зручним способом представлення дат і часу є струни. Однак, щоб працювати з цими датами й часом арифметичним способом (наприклад, обчислювати різницю в часі, додавати або вилучати час тощо), нам потрібно перетворити їх на datetime об'єкт

Одне з найпоширеніших джерел дата і час у рядковому форматі це REST API, які повертають агностичні рядки, які потім можна конвертувати в інші формати.

Крім того, часові пояси є звичайним головним болем, коли справа доходить до роботи з об’єктами datetime, тому нам також потрібно буде думати про це під час конвертації.

У цьому посібнику ми розглянемо, як перетворити рядок дати/часу на a datetime об’єкт у Python, використовуючи вбудований datetime модуль, а також модулі сторонніх виробників, такі як dateutil, arrow і Maya з урахуванням часових поясів.

Перетворення рядків за допомогою datetime

Команда дата, час модуль складається з трьох різних типів об'єктів: 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 формат (РРРР-ММ-ДДТГГ:ММ:СС.мммммм). Якщо наш вхідний рядок створити a 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.

Оскільки це a datetime об'єкт, ми можемо назвати date() та time() методи безпосередньо на ньому. Як ви можете бачити з результату, він друкує частину «дата» та «час» вхідного рядка!

Формат жетонів

Варто витратити хвилинку, щоб зрозуміти жетони формату - "%Y-%m-%d %H:%M:%S.%f" від раніше.

Кожен токен представляє різну частину дати-часу, як-от день, місяць, рік, день місяця чи тижня тощо. список підтримуваних токенів є достатньо великим, щоб уможливити різноманітне форматування. Деякі з поширених, які ми також використовували раніше:

  • %Y: Рік (4 цифри)
  • %m: Місяць
  • %d: День місяця
  • %H: година (24 години)
  • %M: Хвилини
  • %S: Секунди
  • %f: мікросекунди

Примітка: Очікується, що всі ці маркери, крім року, будуть доповнені нулем (тобто серпень є 8-м місяцем і доповнений нулем до 08).

Використання маркерів форматування strptime() для перетворення рядка в інший формат дати й часу

Якщо формат рядка відомий, його можна легко розібрати до a 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)

Вхідний рядок мав один формат – «Jul 17 2022 9:20AM». Знаючи цей формат, ми зіставили складові елементи у формат 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 поле має бути a datetime.timezone об'єкт, що позначає інформацію про часовий пояс. Його None за замовчуванням і означає, що об’єкт datetime не відповідає часовому поясу. Дуже поширеною зовнішньою бібліотекою для обробки часових поясів є pytz. Ви можете встановити 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», на дату й час, а потім локалізувати у часовий пояс «Америка/Нью-Йорк»:

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)

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

Отримуємо те саме значення дати і часу, залік на -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 годин.

Перетворення рядка на дату й час за допомогою сторонніх бібліотек

Пітона datetime модуль може перетворювати всі різні типи рядків у a datetime об'єкт. Але основна проблема полягає в тому, що для цього вам потрібно створити відповідний рядок коду форматування, який strptime() може зрозуміти. Створення цього рядка вимагає часу, і це ускладнює читання коду.

Замість цього ми можемо використовувати інші бібліотеки сторонніх розробників, щоб полегшити роботу.

У деяких випадках ці бібліотеки сторонніх розробників також мають кращу вбудовану підтримку для маніпулювання та порівняння дат і часу, а деякі навіть мають вбудовані часові пояси, тому вам не потрібно включати додатковий пакет PyTz.

Давайте розглянемо деякі з цих бібліотек у наступних розділах.

Перетворіть String на 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

майя також дуже легко аналізувати рядок і змінювати часові пояси. Щоб легко перетворити рядок за допомогою Python Maya:

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.

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

стрілка це ще одна бібліотека для роботи з датою та часом у 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

Щоб правильно розібрати рядки дати й часу, які закоментовані, вам потрібно передати відповідний жетони формату щоб дати бібліотеці підказки щодо того, як його розібрати.

Висновок

У цій статті ми показали різні способи розбору рядка до a datetime об'єкт у Python. Ви можете вибрати стандартний Python datetime бібліотеку або будь-яку зі сторонніх бібліотек, згаданих у цій статті, серед багатьох інших.

Основна проблема з дефолтом datetime пакет полягає в тому, що нам потрібно вручну вказати код аналізу майже для всіх форматів рядків дати й часу. Отже, якщо ваш формат рядка зміниться в майбутньому, вам, імовірно, також доведеться змінити свій код. Але багато сторонніх бібліотек, як-от згадані тут, обробляють це автоматично.

Ще одна проблема, з якою ми стикаємося, — це часові пояси. Найкращий спосіб впоратися з ними — це завжди зберігати час у своїй базі даних у форматі UTC, а потім за потреби перетворювати його на місцевий часовий пояс користувача.

Ці бібліотеки підходять не лише для аналізу рядків, але й для багатьох різних типів операцій, пов’язаних із датою та часом. Я раджу вам переглянути документи, щоб детально вивчити функції.

Часова мітка:

Більше від Stackabuse