`Fromtimestamp` Python делает дискретный переход - PullRequest
7 голосов
/ 29 марта 2012

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

(Я также использую time.mktime для преобразования объекта даты и времени в время эпохи, , как предложено Рэймондом Хеттингером . Я не уверен, является ли это релевантной информацией для этого вопроса, поэтому я говоря это на всякий случай.)

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))

Преобразование его в дату и время, используя 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 совершает скачок.

Ответы [ 2 ]

9 голосов
/ 30 марта 2012

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

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

Тем не менее, общепринятым является постоянная работа с UTCи избегать всех проблем с летним временем (используйте местный часовой пояс только для окончательного отображения).Используйте 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)

PS Вы также можете установить локаль вашего процесса в UTC (но это может не сработать в не-POSIX ОС):1017 *

>>> import os,time
>>> os.environ["TZ"] = "UTC"
>>> time.tzset()
>>> datetime.datetime.fromtimestamp(x)
datetime.datetime(2012, 3, 30, 0, 0)
4 голосов
/ 29 марта 2012

Легко.30 марта - это, вероятно, переход на летнее время в вашем часовом поясе.

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

...