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, но я только что обнаружил, что я не могу достичь этой простой функции в datetime и должен ввести больше зависимостей?

3 ответов


часть проблемы здесь заключается в том, что строки обычно используются для представления часовых поясов на самом деле не уникальна. "EST "означает только" Америка/New_York " для людей в Северной Америке. Это ограничение в API времени C, и решение Python... добавить полные функции tz в какой-то будущей версии в любой день, если кто-то готов написать PEP.

вы can форматировать и анализировать часовой пояс как смещение, но это теряет информацию о летнее время / летнее время (например, вы не могу отличить "Америку/Феникса" от "Америки/Лос-Анджелеса" летом). Вы можете отформатировать часовой пояс как аббревиатуру из 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.


к сожалению, strptime() может обрабатывать только часовой пояс, настроенный вашей ОС,а затем только как смещение времени. От документация:

поддержка %Z директива основана на значениях, содержащихся в tzname и Ли daylight - Это правда. Из-за этого он специфичен для платформы, за исключением распознавания UTC и GMT, которые всегда известны (и считаются non-daylight savings часовой пояс.)

strftime() официально не поддерживает %z.

С python-dateutil чтобы поддержать разбор часового пояса, я боюсь.


вот мой ответ на 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