Як я можу перетворити об’єкт дати в мілісекунди з епохи (часу Unix) в Python?


353

У мене є об’єкт Python, datetimeякий я хочу перетворити на час Unix, або секунди / мілісекунди з епохи 1970 року.

Як це зробити?



Якщо ви приземлилися тут, просто бажаючи поточної епохи секунд з мілісекундною точністю, спробуйте, $ python -c 'import time; print(time.time())'що дало:1584487455.698623
MarkHu

Відповіді:


471

Мені здається, що це найпростіший спосіб зробити це

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 вер <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)коли розглядається часовий пояс.
ahj

35
Чому о, чому datetime.utcfromtimestamp(0)повертає дату без tzinfo? Це прямо там у назві методу, utc fromtimetamp. Для того, щоб зробити це не наївно, я повинен зробити щось подібне datetime.utcfromtimestamp(0).replace(tzinfo=pytz.UTC). Це необхідно, якщо dtвідомий часовий пояс, інакше ви отримаєтеTypeError: can't subtract offset-naive and offset-aware datetimes
FGreg

168

У Python 3.3 додано новий метод timestamp:

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

У вашому запитанні було вказано, що вам потрібні мілісекунди, які ви можете отримати так:

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

Якщо ви користуєтесь timestampнаївним об’єктом дати, то передбачається, що він знаходиться в локальному часовому поясі. Використовуйте об'єкти дат, які знають часовий пояс, якщо це не те, що ви маєте намір статися.


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) datetime знаходиться в UTC. Тому завжди краще встановити часовий пояс: datetime.datetime.now(pytz.timezone('Europe/Paris')).timestamp() == datetime.datetime.now(pytz.utc).timestamp() == datetime.datetime.utcnow().timestamp()але не (завжди) рівний datetime.datetime.now().timestamp()(останній дорівнює лише решті, якщо місцевий тз - UTC ...)
Блу,

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
Btw, strearch ("% s") повертає для мене порожній рядок. Другий спосіб прекрасно працює.
Павло Власов

23
Є лише друга точність
shuckc

6
'% s' не підтримується Python, наприклад, він може бути відсутнім у Windows. .timetuple()повертає tm_isdst=-1це змушує mktime()здогадуватися. Він може здогадатися неправильно під час DST (50% шансу помилки +/- година). Обидва '% s' mktime()можуть використовувати неправильне зміщення ультразвукового сигналу для дат із минулого. Вам потрібен історичний db часового поясу, такий як наданий pytzмодулем, щоб надійно перетворити місцевий час на часову мітку POSIX (якщо ОС вже не надає такий db)
jfs

1
time.mktime(ts.timetuple())де ts - об’єкт
дати

1
@suhail: прочитайте мій коментар вище про mktime/timetuple. Також timetuple()знімає частки секунди, і питання полягає в тому, щоб позначити часову позначку з мілісекундною точністю.
jfs


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


2
@JFSebastian Дякую за голову! насправді немає ніякого догляду. Якщо ваш сервер знаходиться в локальному часі замість UTC, це змінить значення. Я не знайшов (поки що) жодної вагомої причини для встановлення серверів нічого іншого, крім UTC. Мій мото "писати UTC, читати місцевий час", щоб ви завжди знали, де ви зупиняєтесь ...
estani

2
Ви завжди можете використовувати Calendar.timegm замість mktime, щоб уникнути проблеми mktime, намагаючись відгадати часовий пояс.
Декко

13

@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))

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 або часова марка з мілісекундною точністю). Незважаючи на те, обидва питання вже були задані і відповіді в інших місцях. Сказавши це, я думаю, що відповіді тут є найшвидшими та найяснішими, щоб люди ступали і робили хорошу роботу, щоб проілюструвати різні рішення проблеми.
corford

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


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

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

9
Це неправильно! Тимплет не включає мілісекунд, тому 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;
    } 

2
Питання щодо мови Python
Stéphane
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.