Python: конвертировать тайм-код UTC в метку времени UTC

Моя проблема: мне нужно преобразовать тайм-код 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 (т.е. текущий "некоторое время" в Гринвичской Англии).

Ответ 1

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

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, поэтому вы можете сравнить ее с вашим выходом.