Как я могу преобразовать объект datetime в миллисекунды с начала эпохи (unix time) в Python?

356

У меня есть datetimeобъект Python, который я хочу преобразовать в unix time или секунды / миллисекунды с 1970 года.

Как мне это сделать?

Суперструнисты
источник
Если вы приземлились здесь только в $ python -c 'import time; print(time.time())'1584487455.698623
ожидании

Ответы:

474

Мне кажется, что самый простой способ сделать это

import datetime

epoch = datetime.datetime.utcfromtimestamp(0)

def unix_time_millis(dt):
    return (dt - epoch).total_seconds() * 1000.0
Софи Альперт
источник
32
Пока что это лучшее решение (если версия Python> 2.7). Потому что реализация %sзависит от ОС! Таким образом, любой хочет, чтобы код работал надежно, независимо от того, какую ОС НИКОГДА не использовать %s. Для 2.3 <py ver <2.7. Можно просто построить total_seconds()так:delta.days*86400+delta.seconds+delta.microseconds/1e6
Ван
14
примечание: dtдолжно быть в UTC (не локально). Смотрите аналогичный ответ с поддержкой Python 2.6 / 3
jfs
7
Стоит отметить, что если все, что вам нужно, это настоящая временная метка Unix, как определено здесь en.wikipedia.org/wiki/Unix_time (и поэтому будет использовать только функцию unix_time из этого ответа), то вам следует обернуть delta.total_seconds () с int в избежать окончания с поплавком
корфорд
1
вычисленная с использованием эпохи utcfromtimestamp(0)может вызвать смещение 'tz' только в том случае, если 'tz' не равно 0. Это потому, что dt в dt- epochнем вычислено 'tz', где как эпоха - время UTC. Лучший способ рассчитать эпоху - это epoch = datetime.datetime(1970, 1, 1)когда учитывается часовой пояс.
ах,
35
Почему datetime.utcfromtimestamp(0)возвращается datetime без tzinfo? Это прямо в имени метода, utc fromtimestamp. Для того, чтобы сделать его не наивным, я должен сделать что-то вроде datetime.utcfromtimestamp(0).replace(tzinfo=pytz.UTC). Это необходимо, если вам dtизвестен часовой пояс, иначе вы получитеTypeError: can't subtract offset-naive and offset-aware datetimes
FGreg
171

В Python 3.3 добавлен новый метод timestamp:

import datetime
seconds_since_epoch = datetime.datetime.now().timestamp()

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

milliseconds_since_epoch = datetime.datetime.now().timestamp() * 1000

Если вы используете timestampнаивный объект datetime, то предполагается, что он находится в местном часовом поясе. Используйте объекты datetime с учетом часового пояса, если это не то, что вы собираетесь делать.

eshizhan
источник
28
Примечание: .timestamp()метод предполагает, что наивный ввод даты и времени находится в местном часовом поясе (и местное время может быть неоднозначным). Если это в UTC, тогда используйте dt.replace(tzinfo=timezone.utc).timestamp()вместо этого .
JFS
11
datetime.timestamp () возвращает эпохальные секунды в виде числа с плавающей запятой. Чтобы получить миллисекунды: int (datetime.timestamp () * 1000)
Solar.gy
9
Этот ответ не является копируемым и вставляемым примером, в духе нечеловеческих документов на docs.python.org/3/library/… - это: datetime.datetime.timestamp(datetime.datetime.now())
MarkHu
3
В версии 3.6 (как минимум) функция datetime.timestamp () предполагает, что дата-время наивного времени (tzinfo = None) указана в формате UTC. Так что всегда лучше, чтобы ваш часовой пояс был установлен: datetime.datetime.now(pytz.timezone('Europe/Paris')).timestamp() == datetime.datetime.now(pytz.utc).timestamp() == datetime.datetime.utcnow().timestamp()но не (всегда) равным datetime.datetime.now().timestamp()(этот последний равен только остальным, если локальный tz UTC ...)
Bluu
1
Для вашего интереса обратное] fromtimestamp( docs.python.org/3/library/… )
Flimm
98
>>> import datetime
>>> # replace datetime.datetime.now() with your datetime object
>>> int(datetime.datetime.now().strftime("%s")) * 1000 
1312908481000

Или с помощью модуля времени (и без форматирования даты):

>>> import datetime, time
>>> # replace datetime.datetime.now() with your datetime object
>>> time.mktime(datetime.datetime.now().timetuple()) * 1000
1312908681000.0

Ответ с помощью: http://pleac.sourceforge.net/pleac_python/datesandtimes.html

Документация:

Мик
источник
6
Кстати, strftime ("% s") возвращает пустую строку для меня. Второй способ работает отлично.
Павел Власов
23
Только имеет вторую точность
shuckc
6
«% s» не поддерживается Python, например, он может отсутствовать в Windows. .timetuple()возвращает tm_isdst=-1силы mktime()угадать. Во время летнего времени он может ошибочно угадать (50% вероятности ошибки +/- час). Оба "% s" и mktime()могут использовать неправильное смещение utc для дат из прошлого. Вам нужна историческая дБ часового пояса, например, предоставленная pytzмодулем, для надежного преобразования локального времени в метку времени POSIX (если только ОС не предоставляет такую ​​базу данных)
jfs
1
time.mktime(ts.timetuple())где ts - объект даты и времени в python
suhailvs
1
@suhail: прочитайте мой комментарий выше о mktime/timetuple. Также timetuple()обрезает доли секунды, и вопрос в том, чтобы получить метку времени с точностью до миллисекунды.
JS
13

Вот как я это делаю:

from datetime import datetime
from time import mktime

dt = datetime.now()
sec_since_epoch = mktime(dt.timetuple()) + dt.microsecond/1000000.0

millis_since_epoch = sec_since_epoch * 1000
estani
источник
2
@JFSebastian Спасибо за внимание! на самом деле нет никакого рассматриваемого. Если ваш сервер работает по местному времени вместо UTC, это будет иметь значение. Я не нашел (пока) каких-либо веских причин для установки серверов, кроме UTC. Мой
девиз: «Пишите
2
Вы всегда можете использовать calendar.timegm вместо mktime, чтобы избежать проблемы, когда mktime пытается угадать часовой пояс.
Decko
13

Рекомендации из Python 2.7 документации для timeмодуля

Преобразование между представлениями времени

Анкур Агарвал
источник
@ChristopherBull Просто разделите количество миллисекунд на 1000, чтобы получить секунды
Джонас
5
Вы неправильно поняли и неправильно поняли. Секунды все готовы доступны в вышеуказанных функциях. Вы можете преобразовать его в миллисекунды, но это будет с точностью до секунды.
Кристофер Булл
1
Этот ответ использует timeмодуль, но ОП спросил о datetimeмодуле. FWIW, самая простая текущая эпохаint(time.time())
MarkHu
7
from datetime import datetime
from calendar import timegm

# Note: if you pass in a naive dttm object it's assumed to already be in UTC
def unix_time(dttm=None):
    if dttm is None:
       dttm = datetime.utcnow()

    return timegm(dttm.utctimetuple())

print "Unix time now: %d" % unix_time()
print "Unix timestamp from an existing dttm: %d" % unix_time(datetime(2014, 12, 30, 12, 0))
corford
источник
timegm()работает только с временем UTC. Он не использует, tm_isdstпоэтому вы можете использовать utcnow.timetuple()вместо utcnow.utctimetuple(). Примечание: использование naive_local_datetime.utctimetuple()было бы неправильно здесь. Местное время не переводится в utc. Также timetuple()вызывайте полоски доли секунды от результата (имеет ли это значение, зависит от приложения). Также вопрос задается о * милли * секундах, а не секундах
JFS
Я предпочитаю использовать utcnow () и utctimetuple (), чтобы сделать код абсолютно ясным, что вы имеете дело с UTC (и поэтому любой, кто читает его, не должен помнить, что timegm является только UTC). utctimetuple () не подразумевает перевод на наивный объект dttm (следовательно, инициирование dttm с помощью utcnow ()). Кроме того, вопрос упомянутых секунд или миллисекунд.
Корфорд
Примечание: следовало бы сказать в последнем комментарии, что я прочитал вопрос как намекающий на то, что ему нужны секунды или миллисекунды (вероятно, моя ошибка). Для миллиса просто умножьте на 1000 (как подсказывает самый лучший ответ).
Корфорд
utctimetuple()полоски доли секунды. Умножение на 1000не вернет их.
JFS
1
Из-за того, как ОП задал этот вопрос, неясно, что именно он / она хотел (т.е. настоящая метка времени Unix или метка времени с точностью до миллисекунды). Несмотря на это, оба вопроса уже были заданы и даны ответы в другом месте. Сказав это, я думаю, что ответы здесь являются самыми быстрыми и самыми чистыми для людей, чтобы понять и сделать хорошую работу, иллюстрируя различные решения проблемы.
Корфорд
3
>>> import datetime
>>> import time
>>> import calendar

>>> #your datetime object
>>> now = datetime.datetime.now()
>>> now
datetime.datetime(2013, 3, 19, 13, 0, 9, 351812)

>>> #use datetime module's timetuple method to get a `time.struct_time` object.[1]
>>> tt = datetime.datetime.timetuple(now)
>>> tt
time.struct_time(tm_year=2013, tm_mon=3, tm_mday=19, tm_hour=13, tm_min=0, tm_sec=9,     tm_wday=1, tm_yday=78, tm_isdst=-1)

>>> #If your datetime object is in utc you do this way. [2](see the first table on docs)
>>> sec_epoch_utc = calendar.timegm(tt) * 1000
>>> sec_epoch_utc
1363698009

>>> #If your datetime object is in local timeformat you do this way
>>> sec_epoch_loc = time.mktime(tt) * 1000
>>> sec_epoch_loc
1363678209.0

[1] http://docs.python.org/2/library/datetime.html#datetime.date.timetuple

[2] http://docs.python.org/2/library/time.html

Jinesh
источник
3

Вот еще одна форма решения с нормализацией вашего объекта времени:

def to_unix_time(timestamp):
    epoch = datetime.datetime.utcfromtimestamp(0) # start of epoch time
    my_time = datetime.datetime.strptime(timestamp, "%Y/%m/%d %H:%M:%S.%f") # plugin your time object
    delta = my_time - epoch
    return delta.total_seconds() * 1000.0
arhoskins
источник
2

Немного кода панд:

import pandas

def to_millis(dt):
    return int(pandas.to_datetime(dt).value / 1000000)
Волхв
источник
1
import time
seconds_since_epoch = time.mktime(your_datetime.timetuple()) * 1000
MattoTodd
источник
9
Это не верно! Timetuple не включает миллисекунды, поэтому mktime не вернет эпоху с миллисекундным разрешением. Это бесполезно в этом случае.
Ван
@Wang - вы правы, сэр, это не возвращает миллис, только секунды
MattoTodd
1
Если вы удалите * 1000, вы получите seconds_since_epoch. Выражаю этот ответ, потому что сейчас меня не волнуют миллисекунды.
Майкл Шепер
0

Вот функция, которую я сделал на основе ответа выше

def getDateToEpoch(myDateTime):
    res = (datetime.datetime(myDateTime.year,myDateTime.month,myDateTime.day,myDateTime.hour,myDateTime.minute,myDateTime.second) - datetime.datetime(1970,1,1)).total_seconds()
    return res

Вы можете обернуть возвращаемое значение следующим образом: str (int (res)) Чтобы вернуть его без десятичного значения, которое будет использоваться в качестве строки, или просто int (без str)

Джил Аллен
источник
-14

Это другое решение для скрытой даты и времени в unixtimestampmillis.

private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

    public static long GetCurrentUnixTimestampMillis()
    {
        DateTime localDateTime, univDateTime;
        localDateTime = DateTime.Now;          
        univDateTime = localDateTime.ToUniversalTime();
        return (long)(univDateTime - UnixEpoch).TotalMilliseconds;
    } 
samsanthosh2008
источник
2
Вопрос о языке Python
Стефан