Ответ 1
У меня есть строки в формате hms в формате YMD, в которых был отключен часовой пояс. Но я знаю, что они в восточное время с летним временем.
Портативный способ - использовать pytz
:
#!/usr/bin/env python
from datetime import datetime
import pytz # $ pip install pytz
naive_dt = datetime.strptime('2015-04-20 21:12:07', '%Y-%m-%d %H:%M:%S')
tz = pytz.timezone('US/Eastern')
eastern_dt = tz.normalize(tz.localize(naive_dt))
print(eastern_dt)
# -> 2015-04-20 21:12:07-04:00
Я пытаюсь преобразовать их в временные метки эпохи для времени UTC.
timestamp = (eastern_dt - datetime(1970, 1, 1, tzinfo=pytz.utc)).total_seconds()
# -> 1429578727.0
Смотрите Преобразование datetime.date в метку времени UTC в Python.
В коде есть несколько проблем:
-
time.mktime()
может возвращать неправильный результат для неоднозначного времени ввода (вероятность 50%), например, во время перехода "назад" DST на осень -
time.mktime()
иdatetime.fromtimestamp()
могут не работать для прошлых/будущих дат, если у них нет доступа к базе данных хронологического времени в системе (в частности, Windows) -
localize(dt)
может возвращать неправильный результат для двусмысленного или несуществующего времени, то есть во время перехода DST. Если вы знаете, что время соответствует летнему времени, используйтеis_dst=True
.tz.normalize()
необходимо здесь, чтобы отрегулировать возможные несуществующие времена на входе -
utc_dt.strftime("%s")
не переносится и не поддерживает объект tzinfo. Он интерпретирует ввод как локальное время, то есть возвращает неверный результат, если ваш часовой пояс не является UTC.
Можно ли просто установить is_dst = True?
Вы можете, если вы не возражаете получить неточные результаты для двусмысленных или несуществующих времен, например, существует переход на летнее время в период падения в Америке /New _York:
>>> from datetime import datetime
>>> import pytz # $ pip install pytz
>>> tz = pytz.timezone('America/New_York')
>>> ambiguous_time = datetime(2015, 11, 1, 1, 30)
>>> time_fmt = '%Y-%m-%d %H:%M:%S%z (%Z)'
>>> tz.localize(ambiguous_time).strftime(time_fmt)
'2015-11-01 01:30:00-0500 (EST)'
>>> tz.localize(ambiguous_time, is_dst=False).strftime(time_fmt) # same
'2015-11-01 01:30:00-0500 (EST)'
>>> tz.localize(ambiguous_time, is_dst=True).strftime(time_fmt) # different
'2015-11-01 01:30:00-0400 (EDT)'
>>> tz.localize(ambiguous_time, is_dst=None).strftime(time_fmt)
Traceback (most recent call last):
...
pytz.exceptions.AmbiguousTimeError: 2015-11-01 01:30:00
Часы возвращаются в 2a.m. в первое воскресенье ноября:
Флаг значений is_dst
может иметь три значения:
-
False
- по умолчанию, предположим зимнее время -
True
- принять летнее время -
None
- создать исключение для неоднозначных/несуществующих времен.
is_dst
значение игнорируется для существующих уникальных локальных времен.
Здесь приведен график из PEP 0495 - Локальное значение времени > , которое иллюстрирует переход DST:
Местное время повторяется дважды в складке (летнее время - до складки, зима - после).
Чтобы иметь возможность автоматически дистанцировать локальное время, вам нужна дополнительная информация, например, если вы читаете серию локальных раз, то это может помочь, если вы знаете, что они отсортированы: Анализ устаревших временных меток в локальное время (до UTC) при наблюдении за летним временем.