Директива часового пояса Python '%z' для datetime.strptime() недоступна

Использование шаблона '%z' для datetime.strptime()

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

date = "[24/Aug/2014:17:57:26"
dt = datetime.strptime(date, "[%d/%b/%Y:%H:%M:%S")  

За исключением того, что я не могу перехватить всю строку даты с часовым поясом, используя шаблон %z, как указано здесь

date_tz = 24/Aug/2014:17:57:26 +0200
dt = datetime.strptime(date, "[%d/%b/%Y:%H:%M:%S %z]")
>>> ValueError: 'z' is a bad directive in format '[%d/%b/%Y:%H:%M:%S %z]'

Потому что, как говорится в отчете об ошибке

strftime() реализуется для каждой платформы.

Я уточняю, что с наивной директивой tzinfo '%Z' такой проблемы нет.

Обходной путь: преобразование строки tzinfo в объект tzinfo

Я могу отлично найти следующий обходной путь, преобразовав строку формата времени GST в объект tzinfo [как предложено здесь][4] с помощью модуль dateutil, а затем вставьте tzinfo в объект datetime

Вопрос: сделать %z доступным для моей платформы?

Но поскольку мне, очевидно, понадобится шаблон %z для дальнейшего проекта, я хотел бы найти решение, позволяющее избежать этого обходного пути и использовать внешний модуль для этой простой задачи. Можете ли вы предложить мне что-нибудь почитать об этом? Я предположил, что более новая версия Python (у меня 2.7) справится с этим, но я бы не хотел менять свою версию сейчас из-за этой маленькой, но важной детали.

[РЕДАКТИРОВАТЬ]

Что ж, увидев комментарии, я переформулировал свой вопрос, как анализировать индикатор часового пояса электронной почты с помощью strptime(), не зная местного времени?


person c24b    schedule 02.10.2014    source источник
comment
Если он не поддерживается базовой библиотекой C, от которой зависит Python, вы его не получите.   -  person Mark Ransom    schedule 02.10.2014
comment
Так что я полагаю, что у меня нет другого выбора, кроме как делать каждый раз этот уродливый и неэффективный обходной путь?   -  person c24b    schedule 02.10.2014
comment
Я не знаю, как это сделать, и я уверен, что вопрос задавался раньше.   -  person Mark Ransom    schedule 02.10.2014
comment
Информацию о часовом поясе можно найти на pytz -› pytz.sourceforge.net.   -  person Gohn67    schedule 02.10.2014
comment
pytz не преобразует строковый формат, например «+0400», в объект tzinfo. Мне нужно, чтобы он учитывал не мою локаль, а входную строку.   -  person c24b    schedule 03.10.2014
comment
Связано с stackoverflow. ком/вопросы/23940551/   -  person wanghq    schedule 04.11.2014


Ответы (3)


strptime() реализован на чистом Python. В отличие от strftime(); это [какие директивы поддерживаются] не зависит от платформы. %z поддерживается начиная с Python 3.2:

>>> from datetime import datetime
>>> datetime.strptime('24/Aug/2014:17:57:26 +0200', '%d/%b/%Y:%H:%M:%S %z')
datetime.datetime(2014, 8, 24, 17, 57, 26, tzinfo=datetime.timezone(datetime.timedelta(0, 7200)))

как разобрать индикатор часового пояса электронной почты с помощью strptime(), не зная местного времени?

В Python 2.7 нет конкретной реализации часового пояса. Вы можете легко реализовать синтаксический анализ смещения UTC, см. Как анализировать даты со строкой часового пояса -0400 в python?

person jfs    schedule 03.10.2014
comment
Обратите внимание, что %z соответствует только GMT, UTC и time.tzname. Это ограничение: bugs.python.org/issue22377 - person xtreak; 25.09.2018
comment
@xtreak не путайте %Z (сокращение часового пояса) и %z (числовое смещение). - person jfs; 25.09.2018
comment
@jfs Спасибо, что поймали :) - person xtreak; 26.09.2018

Продолжая ответ @j-f-sebastians, вот исправление для python 2.7.

Вместо того, чтобы использовать:

datetime.strptime(t,'%Y-%m-%dT%H:%M %z')

используйте timedelta для учета часового пояса, например:

from datetime import datetime,timedelta
def dt_parse(t):
    ret = datetime.strptime(t[0:16],'%Y-%m-%dT%H:%M')
    if t[17]=='+':
       ret-=timedelta(hours=int(t[18:20]),minutes=int(t[20:]))
    elif t[17]=='-':
       ret+=timedelta(hours=int(t[18:20]),minutes=int(t[20:]))
    return ret

print(dt_parse('2017-01-12T14:12 -0530'))
person Uri Goren    schedule 17.08.2016
comment
разве это не должно быть timedelta(hours=int(t[19:22]),minutes=int(t[23:])) ?? - person guilhermecgs; 20.10.2016

Ответ Ури великолепен, спас мне жизнь, но когда у вас есть USE_TZ = True, вам нужно быть осторожным со временем, чтобы избежать предупреждения «RuntimeWarning: DateTimeField», если вы добавите utc к возврату.

import pytz
from datetime import datetime, timedelta
def dt_parse(t):
    ret = datetime.strptime(t[0:19],'%Y-%m-%dT%H:%M:%S')
    if t[23]=='+':
        ret-=timedelta(hours=int(t[24:26]), minutes=int(t[27:]))
    elif t[23]=='-':
        ret+=timedelta(hours=int(t[24:26]), minutes=int(t[27:]))
    return ret.replace(tzinfo=pytz.UTC)
person LaBE    schedule 19.09.2017