Python strptime() и часовые пояса?
У меня есть CSV файл из резервной копии BlackBird IPD, созданный с использованием IPDDump.
Строки даты/времени здесь выглядят примерно так
(где EST
- австралийская часовая зона):
Tue Jun 22 07:46:22 EST 2010
Мне нужно проанализировать эту дату в Python. Сначала я попытался использовать функцию strptime()
из времени datettime.
>>> datetime.datetime.strptime('Tue Jun 22 12:10:20 2010 EST', '%a %b %d %H:%M:%S %Y %Z')
Однако по какой-то причине возвращаемый объект datetime
, похоже, не связан с ним tzinfo
.
Я прочитал эту страницу, который, по-видимому, datetime.strptime
молча отбрасывает tzinfo
, однако я проверил документацию, и я могу "t найти что-либо с этим документом здесь.
Мне удалось получить синтаксический анализ, используя стороннюю библиотеку Python, dateutil, однако мне все еще интересно, как как я неправильно использовал встроенный strptime()
? Есть ли способ получить strptime()
, чтобы хорошо играть с часовыми поясами?
Ответы
Ответ 1
datetime
модуль документации гласит:
Возвращает datetime, соответствующее date_string, проанализированный в соответствии с форматом. Это эквивалентно datetime(*(time.strptime(date_string, format)[0:6]))
.
Видите это [0:6]
? Это получает вас (year, month, day, hour, minute, second)
. Ничего больше. Нет упоминания о часовых поясах.
Интересно, что [Win XP SP2, Python 2.6, 2.7] передача вашего примера в time.strptime
не работает, но если вы удалите "% Z" и "EST", это сработает. Также работает "UTC" или "GMT" вместо "EST". "PST" и "MEZ" не работают. Непонятные.
Стоит отметить, что это было обновлено с версии 3.2, и в той же документации теперь также говорится следующее:
Когда директива% z предоставляется методу strptime(), будет создан осведомленный объект datetime. Для tzinfo результата будет задан экземпляр часового пояса.
Обратите внимание, что это не работает с% Z, поэтому важен случай. Смотрите следующий пример:
In [1]: from datetime import datetime
In [2]: start_time = datetime.strptime('2018-04-18-17-04-30-AEST','%Y-%m-%d-%H-%M-%S-%Z')
In [3]: print("TZ NAME: {tz}".format(tz=start_time.tzname()))
TZ NAME: None
In [4]: start_time = datetime.strptime('2018-04-18-17-04-30-+1000','%Y-%m-%d-%H-%M-%S-%z')
In [5]: print("TZ NAME: {tz}".format(tz=start_time.tzname()))
TZ NAME: UTC+10:00
Ответ 2
Я рекомендую использовать python-dateutil. Его синтаксический анализатор смог разобрать каждый формат даты, который я выбрал на нем до сих пор.
>>> from dateutil import parser
>>> parser.parse("Tue Jun 22 07:46:22 EST 2010")
datetime.datetime(2010, 6, 22, 7, 46, 22, tzinfo=tzlocal())
>>> parser.parse("Fri, 11 Nov 2011 03:18:09 -0400")
datetime.datetime(2011, 11, 11, 3, 18, 9, tzinfo=tzoffset(None, -14400))
>>> parser.parse("Sun")
datetime.datetime(2011, 12, 18, 0, 0)
>>> parser.parse("10-11-08")
datetime.datetime(2008, 10, 11, 0, 0)
и т.д. Не имея дело с формальной бессмысленностью strptime()
... просто бросайте дату на нее, и она делает правильную вещь.
Обновить. К сожалению. Я пропустил в вашем первоначальном вопросе, что вы упомянули, что использовали dateutil
, извините. Но я надеюсь, что этот ответ по-прежнему будет полезен другим людям, которые спотыкаются по этому вопросу, когда у них есть вопросы по синтаксическому анализу и видят полезность этого модуля.
Ответ 3
Строка времени аналогична формату времени в rfc 2822 (формат даты в электронной почте, заголовки http). Вы можете разобрать его, используя только stdlib:
>>> from email.utils import parsedate_tz
>>> parsedate_tz('Tue Jun 22 07:46:22 EST 2010')
(2010, 6, 22, 7, 46, 22, 0, 1, -1, -18000)
Ознакомьтесь с решениями, которые предоставляют объекты datetime с учетом часового пояса для различных версий Python: анализ даты с часовым поясом из электронного письма.
В этом формате EST
семантически эквивалентен -0500
. Хотя, как правило, сокращения часового пояса недостаточно для однозначного определения часового пояса.
Ответ 4
Столкнулся с этой точной проблемой.
Что я в итоге сделал:
# starting with date string
sdt = "20190901"
std_format = '%Y%m%d'
# create naive datetime object
from datetime import datetime
dt = datetime.strptime(sdt, sdt_format)
# extract the relevant date time items
dt_formatters = ['%Y','%m','%d']
dt_vals = tuple(map(lambda formatter: int(datetime.strftime(dt,formatter)), dt_formatters))
# set timezone
import pendulum
tz = pendulum.timezone('utc')
dt_tz = datetime(*dt_vals,tzinfo=tz)