Моя проблема: мне нужно преобразовать тайм-код UTC в метку времени UTC. Но у меня есть некоторые недоумения.
Сначала немного информации:
-
time.mktime(tuple)
: эта функция всегда возвращает метку времени в локальном времени.Это обратная функция localtime(). Его аргументом является struct_time или полный 9-кортеж, который выражает время в локальном времени, а не UTC.
-
calendar.timegm(tuple)
: это возвращает временную метку UTC из поставляемого времени tupleпринимает временный кортеж, такой как возвращаемый функцией gmtime() в модуле времени, и возвращает соответствующее значение временной метки Unix. Фактически, time.gmtime() и timegm() - это другие обратные
Теперь сделаем тест:
>>> from datetime import datetime
>>> import time
>>> import calendar as cal
>>> utc_now = datetime.utcnow()
>>> now = datetime.now()
>>> utc_now
datetime.datetime(2013, 3, 16, 9, 17, 22, 489225)
>>> now
datetime.datetime(2013, 3, 16, 5, 17, 29, 736903)
>>> time.mktime(datetime.timetuple(utc_now)), time.mktime(datetime.timetuple(now))
(1363439842.0, 1363425449.0)
>>> cal.timegm(datetime.timetuple(utc_now)), cal.timegm(datetime.timetuple(now))
(1363425442, 1363411049)
Почему существуют четыре разных значения? И какой из них прав, когда я хочу преобразовать тайм-код UTC в временную метку UTC?
UPDATTE
Я думаю, что нашел ответы на мои недоумения, поэтому позвольте мне объяснить.
Во-первых, нам нужно знать что-то важное:
Существует два типа объектов даты и времени: "наивный" и "осознанный".
Известный объект обладает достаточным знанием применимых алгоритмических и политических корректировок времени, таких как информация о часовом поясе и летнее время, чтобы найти себя относительно других объектов-знакомых. Вспомогательный объект используется для представления определенного момента времени, который не открыт для интерпретации [1].
Наивный объект не содержит достаточной информации, чтобы однозначно найти себя относительно других объектов даты/времени. Является ли наивный объект представляет собой скоординированное универсальное время (UTC), местное время или время в каком-то другом часовом поясе, зависит только от программы, точно так же, как это зависит от программы, независимо от того, представляет ли конкретный номер метры, мили или массу. Наивные объекты легко понять и работать, ценой игнорирования некоторых аспектов реальности.
То, что мы получаем из datetime.utcnow()
или datetime.now()
, - это "наивные" объекты. Это означает, что возвращаемый объект datetime
не говорит о вашем местном времени или времени UTC - он просто представляет "некоторое время" . Он просто инкапсулирует информацию о дате и времени (год, месяц, день, час, минуты, секунды и т.д.). ВАША ответственность связывать это с понятием локального или UTC.
Итак, помните, что наивный объект datetime просто представляет "некоторое время" . Функция datetime.now()
возвращает "некоторое время" , равное вашему текущему времени, а функция datetime.utcnow()
возвращает "некоторое время" , то есть текущее время в Гринвичской Англии (что и есть UTC).
"Некоторое время" - это просто значение даты и времени. И обратите внимание, что в разных местах на Земле "некоторое время" происходит в разное время. Например, если значение "некоторое время" составляет 1 января 10:30, то это будет текущее время в Гринвичской Англии около 5 часов, прежде чем оно станет текущим временем в Нью-Йорке.
Следовательно, мы видим, что есть две вещи: общее значение "некоторое время" и представление о том, что это "некоторое время" становится текущим временем в разных местах в разные "времена". (здесь нет слов, читайте дальше)
Теперь давайте сначала определим, что такое "эпоха". Мы знаем, что "некоторое время" - всего лишь общая ценность времени. Затем эпоха представляет собой "некоторое время" , которое произошло в Гринвичской Англии, где значения параметров: January 1 1970, 00:00:00
.
"Временная метка" - нет. секунд, прошедших с эпоса. Это означает, что отметка времени 0
, когда время было Jan 1, 1970, 00:00:00
в Гринвичской Англии. Но отметка времени была ок. (5 * 60 * 60), когда время было Jan 1, 1970, 00:00:00
в Нью-Йорке.
>>> tt = datetime.timetuple(datetime(1970, 1, 1, 0, 0, 0))
>>> cal.timegm(tt)
0
Таким образом, мы можем видеть, что при изменении местоположения одно и то же значение "некоторое время" Jan 1, 1970, 00:00:00
имеет разные временные метки. Следовательно, когда вы говорите о временной отметке, вам нужно также сказать "какое место" - это связанная с этим временная метка, и насколько на восток или на запад это место связано с Гринвичской Англией. Это местоположение выражается как "часовой пояс".
Теперь каждая система (компьютер) настроена на часовой пояс, и все временные метки, связанные с этим часовым поясом, фактически становятся "локальными". UTC является глобальной ссылкой.
Итак, скажем, у вас есть значение X
для "некоторого времени", которое преобразуется в:
-
Y
отметка времени в ваше местное время -
Z
метка времени в UTC
то это означает, что Y
no. секунд потребуется, чтобы "некоторое время" стало текущим временем вашего местоположения, и Z
никакие секунды не пройдут, чтобы текущее время в Гринвичской Англии стало "некоторым временем".
Теперь, наконец, вернемся к нашим функциям mktime
и timegm
. Они занимают временные кортежи, что является просто еще одним представлением "некоторое время" . Помните, что мы передаем им наивное время, которое не имеет никакого представления о локальном или UTC.
Скажем, X
является кортежем времени, представляющим наивное "некоторое время" . Тогда
-
mktime(X)
вернет no. секунд, которые должны пройти, чтобы ваше местное текущее время стало таким "некоторое время" , и -
timegm(X)
вернет количество секунд, которое нужно потратить, чтобы сделать текущее время Гринвичской Англии равным этому "некоторое время" .
В приведенном выше примере now
и utc_now
представляют наивное "некоторое время" , и когда мы передаем эти значения "некоторое время" в mktime
и timegm
, они просто возвращают no. секунд, которые должны пройти для соответствующих мест (ваше местоположение и Гринвичская Англия), чтобы иметь свое текущее время в том, что "некоторое время" .
Наконец, вернемся к моей проблеме: мне нужно преобразовать тайм-код UTC в метку времени UTC.
Во-первых, нет понятия "UTC time-tuple" - это просто "некоторое время" . Если мне нужно преобразовать его в UTC, я просто использую timegm
:
cal.timegm(datetime.timetuple(utc_now))
который даст мне временную метку для текущего времени UTC (т.е. текущий "некоторое время" в Гринвичской Англии).