Преобразуйте datetime в unix timestamp и преобразуйте его обратно в python
Я dt = datetime(2013,9,1,11), и я хотел бы получить временную метку Unix этого объекта datetime.
когда я делаю dt - datetime(1970,1,1)).total_seconds() Я получил метку 1378033200.
при преобразовании его обратно через datetime.fromtimestamp я получил datetime.datetime(2013, 9, 1, 6, 0).
час не совпадает. Что я пропустил здесь?
9 ответов:
то, что вы пропустили здесь, это часовые пояса.
предположительно у вас есть пять часов от UTC, поэтому 2013-09-01T11:00:00 local и 2013-09-01T06:00:00Z-это одно и то же время.
вы должны прочитать верхнюю часть
datetimeдокументы, которые объясняют о часовых поясах и" наивных "и" осведомленных " объектах.если ваш исходный наивный datetime был UTC, способ его восстановления-использовать
utcfromtimestampвместоfromtimestamp.С другой стороны, если ваш исходный наивный datetime был локальным, вы не должны были вычитать из него временную метку UTC в первую очередь; используйте .
или, если у вас был объект aware datetime, вам нужно либо использовать локальную (aware) эпоху с обеих сторон, либо явно конвертировать в UTC и из него.
если у вас есть или вы можете перейти на Python 3.3 или более позднюю версию, вы можете избежать всех этих проблем, просто используя
timestampметод вместо того, чтобы пытаться выяснить, как это сделать себе. И даже если вы этого не сделаете, вы можете рассмотреть заимствуя его исходный код.(и если вы можете ждать Python 3.4, это выглядит как PEP 341 вероятно, чтобы сделать это в финальной версии, что означает, что все вещи J. F. Себастьян и я говорили в комментариях должны быть выполнимы только с stdlib и работать одинаково как на Unix, так и на Windows.)
решение
import time import datetime d = datetime.date(2015,1,5) unixtime = time.mktime(d.timetuple())
вместо этого выражения, чтобы создать временную метку POSIX из
dt,(dt - datetime(1970,1,1)).total_seconds()используйте этот:
int(dt.strftime("%s"))Я получаю правильный ответ в вашем примере, используя второй способ.
EDIT: некоторые последующие действия... После некоторых комментариев (см. ниже), мне было любопытно об отсутствии поддержки или документации для
%sнаstrftime. Вот что я нашел:на Python source на
datetimeиtimeстрокаSTRFTIME_FORMAT_CODESговорит нам:"Other codes may be available on your platform. See documentation for the C library strftime function."так что теперь, если мы
man strftime(в системах BSD, таких как Mac OS X), вы найдете поддержку%s:"%s is replaced by the number of seconds since the Epoch, UTC (see mktime(3))."вот почему
%sработает на системах его вовсе. Но есть лучшие решения проблемы OP (которые учитывают часовые пояса). См. принятый ответ @abarnert здесь.
Если вы хотите конвертировать python datetime в секунды с эпохи, вы должны сделать это явно:
>>> import datetime >>> datetime.datetime(2012,04,01,0,0).strftime('%s') '1333234800' >>> (datetime.datetime(2012,04,01,0,0) - datetime.datetime(1970,1,1)).total_seconds() 1333238400.0в Python 3.3+ вы можете использовать
timestamp()вместо:>>> import datetime >>> datetime.datetime(2012,4,1,0,0).timestamp() 1333234800.0
если ваш объект datetime представляет время UTC, не используйте время.mktime, поскольку он предполагает, что кортеж находится в вашем местном часовом поясе. Вместо этого, используйте календарь.timegm:
>>> import datetime, calendar >>> d = datetime.datetime(1970, 1, 1, 0, 1, 0) >>> calendar.timegm(d.timetuple()) 60
ну, при преобразовании в unix timestamp python в основном принимает UTC, но при обратном преобразовании он даст вам дату, преобразованную в ваш локальный часовой пояс.
посмотреть этот вопрос/ответ; получить часовой пояс, используемый datetime.значение datetime.fromtimestamp ()
вы пропустили информацию о часовом поясе (уже ответил, согласился)
arrowпакета позволяет избежать этой пытки с датами; это уже написано, протестировано, PyPI-опубликовано, кросс-python (2.6 - 3.обман.)все, что вам нужно:
pip install arrow(или добавить в зависимости)решение для вашего случая
dt = datetime(2013,9,1,11) arrow.get(dt).timestamp # >>> 1378033200 bc = arrow.get(1378033200).datetime print(bc) # >>> datetime.datetime(2013, 9, 1, 11, 0, tzinfo=tzutc()) print(bc.isoformat()) # >>> '2013-09-01T11:00:00+00:00'
def dt2ts(dt): import calendar import time from dateutil import tz if dt.tzinfo is None: return int(time.mktime(dt.timetuple())) utc_dt = dt.astimezone(tz.tzutc()).timetuple() return calendar.timegm(utc_dt)Если вы хотите UTC timestamp:
time.mktimeтолько на local dt .Используйтеcalendar.timegmбезопасно, но dt должен быть в зоне utc, поэтому измените зону на utc
для работы с часовыми поясами UTC:
time_stamp = calendar.timegm(dt.timetuple()) datetime.utcfromtimestamp(time_stamp)
Comments