Преобразуйте 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).



час не совпадает. Что я пропустил здесь?

1752   9  

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

    Ничего не найдено.