Як перетворити рядок, відомий часовому поясу, на datetime у Python без dateutil?


80

Мені потрібно перетворити рядок, відомий часовому поясу, як "2012-11-01T04:16:13-04:00"на об’єкт Python datetime.

Я бачив dateutilмодуль, який має функцію синтаксичного аналізу, але я не дуже хочу використовувати його, оскільки він додає залежність.

То як я можу це зробити? Я спробував щось на зразок наступного, але не пощастило.

datetime.datetime.strptime("2012-11-01T04:16:13-04:00", "%Y-%m-%dT%H:%M:%S%Z")

2
Що поганого в додаванні залежності, коли ця залежність точно відповідає вашим вимогам? Звичайно, якби тих самих результатів можна було досягти без додаткового модуля, не було б причин для існування модуля взагалі, чи не так? Наскільки важко вам додати залежність?
Джон Скіт,

Думаю, це, можливо, особиста послуга? Я не дуже хочу вводити в проект цілий великий модуль, оскільки мені потрібна лише крихітна одна функція.
lxyu

2
Яка конкретна вартість додавання залежності до вашого проекту порівняно з вартістю ускладнення розуміння коду, ніж це повинно бути. Ігноруйте той факт, що наразі вам потрібна лише одна функція - зосередьтеся на витратах.
Джон Скіт,

Відповіді:


92

Станом на Python 3.7, datetime.datetime.fromisoformat()може обробляти ваш формат:

>>> import datetime
>>> datetime.datetime.fromisoformat('2012-11-01T04:16:13-04:00')
datetime.datetime(2012, 11, 1, 4, 16, 13, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=72000)))

У старих версіях Python ви не можете, не без безлічі копіткого ручного визначення часового поясу.

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

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

>>> import iso8601
>>> iso8601.parse_date('2012-11-01T04:16:13-04:00')
datetime.datetime(2012, 11, 1, 4, 16, 13, tzinfo=<FixedOffset '-04:00'>)

iso8601це колосальні 4 Кб. Порівняйте python-dateutilзагальну суму 148 КБ.

Починаючи з Python 3.2, Python може обробляти прості часові пояси на основі зсуву та %zаналізуватиме зміщення часових поясів -hhmmта +hhmmчасові пояси в позначці часу. Це означає, що для позначки часу ISO 8601 вам доведеться видалити :часовий пояс:

>>> from datetime import datetime
>>> iso_ts = '2012-11-01T04:16:13-04:00'
>>> datetime.strptime(''.join(iso_ts.rsplit(':', 1)), '%Y-%m-%dT%H:%M:%S%z')
datetime.datetime(2012, 11, 1, 4, 16, 13, tzinfo=datetime.timezone(datetime.timedelta(-1, 72000)))

Відсутність належного аналізу ISO 8601 відстежується у випуску Python 15873 .


Мені здається, datetimeміг би включати щось на зразок iso8601обробки часових поясів ISO 8601 - трохи синтаксичного аналізу та два tzinfoпідкласи.
Eryk Sun

@eryksun: ISO8601 дійсно спрощує часові пояси, але як тільки ви включите ці зсуви в stdlib python, вас завалять непорозуміння, чому часові пояси в реальному житті (які є більш ніж просто зміщення) не працюють тощо.
Мартін Пітерс

1
не так боляче визначати FixedOffset клас. Ось приклад коду
jfs

48

Ось Python Doc для об'єкта datetime за допомогою пакета dateutil ..

from dateutil.parser import parse

get_date_obj = parse("2012-11-01T04:16:13-04:00")
print get_date_obj

5
Це має бути правильною відповіддю для того, щоб робити це без зовнішніх
ліб

6
@Paullo python-dateutil - це саме "зовнішня бібліотека".
Хрещений батько

Найкраща відповідь не спрацювала для мене з кінцевим "Z", але ця відповідь зробила.
user1503941

13

У вихідному питанні є дві проблеми з кодом: :у часовому поясі не повинно бути символу, а рядок формату для "часового поясу як зміщення" має нижній регістр, а %zне верхній регістр %Z.

Це працює для мене в Python v3.6

>>> from datetime import datetime
>>> t = datetime.strptime("2012-11-01T04:16:13-0400", "%Y-%m-%dT%H:%M:%S%z")
>>> print(t)
2012-11-01 04:16:13-04:00

Коли це неправильно, чому print(t)додається двокрапка до зміщення utc?
moooeeeep

@moooeeeep Оскільки за замовчуванням datetime використовує isoformat(sep=' ')для __str__функції, яка друкує зміщення UTC як "+ HH: MM". Використання print(t.strftime("%Y-%m-%dT%H:%M:%S%z"))буде друкувати без часового поясу ":".
Jamie Czuy

3
Наявність двокрапки в часовому поясі не є помилковим. Багато джерел представити свої часи у вигляді рядка: 2012-11-01T04:16:13-04:00. OP намагається проаналізувати цю форму.
DaveL17

2

Ви можете конвертувати так.

date = datetime.datetime.strptime('2019-3-16T5-49-52-595Z','%Y-%m-%dT%H-%M-%S-%f%z')
date_time = date.strftime('%Y-%m-%dT%H:%M:%S.%fZ')

1

Я новачок у Python, але знайшов спосіб конвертувати

2017-05-27T07:20:18.000-04:00 до

2017-05-27T07:20:18 без завантаження нових утиліт.

from datetime import datetime, timedelta

time_zone1 = int("2017-05-27T07:20:18.000-04:00"[-6:][:3])
>>returns -04

item_date = datetime.strptime("2017-05-27T07:20:18.000-04:00".replace(".000", "")[:-6], "%Y-%m-%dT%H:%M:%S") + timedelta(hours=-time_zone1)

Я впевнений, що є кращі способи зробити це, не нарізаючи стільки струн, але це зробило роботу.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.