2013-03-16 6 views
16

Моя проблема: мне нужно преобразовать тайм-код UTC в метку времени UTC. Но у меня есть некоторые недоумения.Python: конвертировать UTC тайм-код в UTC timestamp

Сначала немного информации:

  • time.mktime(tuple): эта функция всегда возвращает метку времени в местного времени.

    Это обратная функция localtime(). Его аргументом является struct_time или полный 9-кортеж, который выражает время в по местному времени, а не по UTC.

  • calendar.timegm(tuple): это возвращает UTC временной метку с прилагаемого временем кортежа

    принимает время кортеж, такие как возвращенная функция 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 нет. секунд потребуется, чтобы «некоторое время» стало текущим временем в вашем местоположении, и Z не потребуется секунд, чтобы текущее время в Гринвичской Англии стало «некоторым временем».

Теперь, наконец, вернемся к нашим функциям mktime и timegm. Они занимают временные кортежи, что является просто еще одним представлением «некоторое время». Помните, что мы передаем им наивное время, которое не имеет понятия о местном или UTC.

Скажем, X - это кортеж, представляющий наивное «некоторое время».Затем

  • mktime(X) вернет номер. секунд, которые должны будут пройти, чтобы ваше местное текущее время стало таким «некоторым временем», и
  • timegm(X) вернет не количество секунд, которое потребуется потратить, чтобы сделать текущее время Гринвичской Англии равным "когда-то".

В приведенном выше примере, now и utc_now представляют наивными «некоторое время», и когда мы кормим эти значения «некоторое время» в mktime и timegm, они просто возвращают нет. секунд, которые должны пройти для соответствующих мест (ваше местоположение и Гринвичская Англия), чтобы иметь свое текущее время в том, что «некоторое время».


Наконец, вернемся к моей проблеме: нужно преобразовать в UTC время кортеж в UTC временной метки.

Во-первых, нет понятия «UTC time-tuple» - это просто «некоторое время». Если мне нужно, чтобы преобразовать его в UTC, я просто использую timegm:

cal.timegm(datetime.timetuple(utc_now)) 

, который даст мне метку времени для текущего времени UTC (т.е., текущего «некоторое время» в Гринвиче Англии).

+1

очень информативный. Благодарю. – smartnut007

+0

Эпоха '1 января 1970 года, 00: 00: 00' ** UTC + 0000 **. Это '31 декабря 1969 года, 19:00:00 EST-0500' в Нью-Йорке. Epoch - это тот же самый экземпляр во всем мире, независимо от того, что показывают локальные часы (локальные часы в Нью-Йорке показывают 19:00 для эпохи POSIX). Временная метка не зависит от местного часового пояса - она ​​точно такая же во всем мире в любой момент времени. – jfs

+0

related: [Преобразование даты datetime.date в метку времени UTC в Python] (http://stackoverflow.com/q/8777753/4279) – jfs

ответ

6

Существует только три разных значений. Эти два значения:

1363425449.0 (time.mktime(datetime.timetuple(now)) 
1363425442 (cal.timegm(datetime.timetuple(utc_now))) 

отличаются лишь 7 секунд, что то, что вы изначально видели, когда вы сбрасывали переменные:

>>> utc_now 
datetime.datetime(2013, 3, 16, 9, 17, 22, 489225) 
>>> now 
datetime.datetime(2013, 3, 16, 5, 17, 29, 736903) 

(Примечание 22-против 29 в секундах части вывода.)

Другие два значения просто ошибочны, поскольку вы применяете неверные аргументы - вы вызываете time.mktime с значениями UTC вместо локальных значений, и вы вызываете cal.timegm с локальными значениями вместо значений UTC , В документации четко сказано, что ожидается - поэтому убедитесь, что вы используете только соответствующие значения. Вы в основном видите свое местное смещение по времени (4 часа, по внешнему виду), применяемое, когда оно не должно быть (в разных направлениях в зависимости от того, где ошибка).

Когда вы диагностируете такие вещи, полезно использовать epochconverter.com, который предоставит вам текущую временную метку Unix, чтобы вы могли сравнить ее с вашим выходом.

+0

В документации НЕ сказано ничего о том, должны ли аргументы быть локальными или UTC. И почему вы говорите, что другие два значения неверны? – treecoder

+1

@ good_computer: Что ты имеешь в виду?В документации *, которую вы указали * для 'mktime', ясно сказано, что она должна быть локальной, а документ *, который вы указали * для' timegm', говорит, что кортеж должен быть видом, возвращаемым из 'gmtime' (это UTC). Если вы передадите значение UTC, когда функция ожидает локальное время или наоборот, тогда функция будет либо применять локальное/UTC-преобразование, когда вы этого не хотите, либо * не * применяете, когда вы делаете * хочу этого. (Жаль, что API не может обнаружить это сам, но это жизнь ... вам нужно быть осторожным) –

+0

@good_computer: Ваша концепция «определенного времени» также известна как «локальная дата и время» во многих рамках - например, «LocalDateTime» в Joda Time. Это дата/время без соответствующего часового пояса. Так у вас на самом деле проблема, или вы отсортированы? –

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