Python datetime strptime() и strftime(): как сохранить информацию о часовом поясе
Смотрите следующий код:
import datetime
import pytz
fmt = '%Y-%m-%d %H:%M:%S %Z'
d = datetime.datetime.now(pytz.timezone("America/New_York"))
d_string = d.strftime(fmt)
d2 = datetime.datetime.strptime(d_string, fmt)
print d_string
print d2.strftime(fmt)
вывод
2013-02-07 17:42:31 EST
2013-02-07 17:42:31
Информация о часовом поясе просто потерялась в переводе.
Если я переключу '% Z' на '% z', я получаю
ValueError: 'z' is a bad directive in format '%Y-%m-%d %H:%M:%S %z'
Я знаю, что могу использовать python-dateutil
, но я просто нашел это bizzare, что я не могу достичь этой простой функции в datetime и должен ввести больше зависимости?
Ответы
Ответ 1
Часть проблемы здесь состоит в том, что строки, обычно используемые для представления часовых поясов, на самом деле не уникальны. "EST" означает только "America/New_York" для людей в Северной Америке. Это ограничение в API-интерфейсе C, а решение Python - это добавить все функции tz в любую будущую версию в любой момент, если кто-то захочет написать PEP.
Вы можете форматировать и анализировать часовой пояс в качестве смещения, но это теряет информацию о летнем/летнем времени (например, вы не можете отличить "Америку/Феникс" от "America/Los_Angeles" летом). Вы можете отформатировать часовой пояс как аббревиатуру из 3 букв, но вы не сможете ее отменить.
Если вы хотите что-то нечеткое и неоднозначное, но обычно то, что вы хотите, вам нужна сторонняя библиотека, например dateutil
.
Если вы хотите что-то действительно недвусмысленное, просто добавьте фактическое имя tz в локальную строку datetime и разделите его на другом конце:
d = datetime.datetime.now(pytz.timezone("America/New_York"))
dtz_string = d.strftime(fmt) + ' ' + "America/New_York"
d_string, tz_string = dtz_string.rsplit(' ', 1)
d2 = datetime.datetime.strptime(d_string, fmt)
tz2 = pytz.timezone(tz_string)
print dtz_string
print d2.strftime(fmt) + ' ' + tz_string
Или... на полпути между этими двумя, вы уже используете библиотеку pytz
, которая может анализировать (в соответствии с некоторыми произвольными, но четко определенными правилами неоднозначности) форматы, такие как "EST". Итак, если вы действительно этого хотите, вы можете оставить %Z
на стороне форматирования, затем вытащить его и проанализировать с помощью pytz.timezone()
, прежде чем передать остальное на strptime
.
Ответ 2
К сожалению, strptime()
может обрабатывать только часовой пояс, настроенный вашей ОС, а затем только как временное смещение. Из документа :
Поддержка директивы %Z
основана на значениях, содержащихся в tzname
, и является ли значение daylight
истинным. Из-за этого он зависит от платформы, за исключением признания UTC и GMT, которые всегда известны (и считаются часами без учета летнего времени).
strftime()
официально не поддерживает %Z
.
Задерживается python-dateutil
для поддержки разбора часового пояса, я боюсь.
Ответ 3
Вот мой ответ в Python 2.7
Печать текущего времени с часовым поясом
from datetime import datetime
import tzlocal # pip install tzlocal
print datetime.now(tzlocal.get_localzone()).strftime("%Y-%m-%d %H:%M:%S %z")
Печать текущего времени с определенным часовым поясом
from datetime import datetime
import pytz # pip install pytz
print datetime.now(pytz.timezone('Asia/Taipei')).strftime("%Y-%m-%d %H:%M:%S %z")
Он напечатает что-то вроде
2017-08-10 20:46:24 +0800