2012-03-28 2 views
6

Я использую datetime.fromtimestamp для преобразования времени эпохи в локальное время. Я обнаружил, что datetime.fromtimestamp совершает дискретный скачок в один час в определенный момент времени, и я совершенно не понимаю, почему он это делает.Python `fromtimestamp` делает дискретный прыжок

(Я также использую time.mktime для преобразования объекта DATETIME в эпоху времени, as suggested by Raymond Hettinger. Я не уверен, является ли соответствующая информация по этому вопросу, так что я говорю это на всякий случай.)

Python 2.7.1+ (r271:86832, Apr 11 2011, 18:05:24) 
[GCC 4.5.2] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import time, datetime 
>>> def datetime_to_epoch_time(datetime_): 
...  return time.mktime(datetime_.timetuple()) + datetime_.microsecond/1e6 
... 

Выбор конкретного времени эпохи:

>>> x = datetime_to_epoch_time(datetime.datetime(2012, 3, 30, 3, 0)) 

Преобразование его в DateTime с помощью fromtimestamp:

>>> datetime.datetime.fromtimestamp(x) 
datetime.datetime(2012, 3, 30, 3, 0) 

Мы получаем время 3 утра.

Теперь давайте преобразуем время это именно одна вторая перед ним:

>>> datetime.datetime.fromtimestamp(x-1) 
datetime.datetime(2012, 3, 30, 1, 59, 59) 

Мы вдруг получить 1:59 утра!

Что случилось? Я знаю, что такие вещи случаются в високосный день, но с каких пор 30 марта високосный день?

Я должен отметить, что это произошло со мной только в Linux, а не в Windows. И я думаю, что разные компьютеры Linux (в разных часовых поясах) имеют разную точку времени, в которой fromtimestamp выполняет скачок.

ответ

4

Простой. 30-го марта, по-видимому, это переход на летнее время в ваш часовой пояс.

Так в тот же день, время действительно идут от 1:59:59 до 3:00:00

+0

Я вижу. Поэтому 'fromtimestamp' знает о часовом поясе, в котором я живу, и знает, какие часы пропускать. Но объекты 'datetime' не знают об этом прыжке: если я вычитаю объект' datetime' за 3 часа из одного за 2am, я получаю «timedelta» одного часа, где я должен получать нуль. –

+0

Как же я делаю объекты 'datetime' осведомленными о моем часовом поясе и заставляю их использовать * точный * некоторый часовой пояс как' fromtimestamp', так что они будут полностью синхронизированы? –

+0

@RamRachum При создании метки времени передайте флаг 'tzinfo'. библиотека 'pytz' может помочь в этом. – Amber

7

fromtimestamp использует «локальное окружение» текущего пользователя, как это определено в библиотеке POSIX C (см man (3) tzset, и документы модуля time).

Если вы действительно хотите получить представление локального времени среды текущего пользователя pytz, в пакете datetime-tz есть функция автоматического обнаружения.

Однако общая мудрость заключается в том, чтобы всегда работать с UTC и избегать всех проблем DST (использовать локальный часовой пояс только для окончательного отображения). Используйте datetime.fromtimestamp(x, tz=pytz.UTC), или, если у вас нет pytz:

>>> datetime.datetime.fromtimestamp(x) 
datetime.datetime(2012, 3, 30, 3, 0) 
>>> datetime.datetime.utcfromtimestamp(x) 
datetime.datetime(2012, 3, 30, 0, 0) 
>>> datetime.datetime.utcfromtimestamp(x-1) 
datetime.datetime(2012, 3, 29, 23, 59, 59) 

P.S. Вы также можете установить локаль вашего процесса в UTC (но это может не работать на ОС, отличных от POSIX):

>>> import os,time 
>>> os.environ["TZ"] = "UTC" 
>>> time.tzset() 
>>> datetime.datetime.fromtimestamp(x) 
datetime.datetime(2012, 3, 30, 0, 0) 
+0

+1 Отличный совет. –

Смежные вопросы