Wie kann ich ein Datum / Uhrzeit-Objekt seit der Epoche (Unix-Zeit) in Python in Millisekunden konvertieren?

354

Ich habe ein Python- datetimeObjekt, das ich seit der Epoche 1970 in Unix-Zeit oder Sekunden / Millisekunden konvertieren möchte.

Wie mache ich das?

SuperString
quelle
Wenn Sie hier gelandet sind und nur aktuelle Epochensekunden mit Millisekundengenauigkeit wollen , versuchen Sie $ python -c 'import time; print(time.time())'1584487455.698623
Folgendes

Antworten:

473

Es scheint mir, dass der einfachste Weg, dies zu tun, ist

import datetime

epoch = datetime.datetime.utcfromtimestamp(0)

def unix_time_millis(dt):
    return (dt - epoch).total_seconds() * 1000.0
Sophie Alpert
quelle
32
Bisher ist dies die beste Lösung (wenn Python-Version> 2.7). Weil die Implementierung von %sOS abhängig ist! Daher möchte jeder, der den Code zuverlässig funktioniert, unabhängig davon, auf welchem ​​Betriebssystem, NIEMALS verwendet werden %s. Für 2.3 <py ver <2.7. Man kann einfach so etwas bauen total_seconds():delta.days*86400+delta.seconds+delta.microseconds/1e6
Wang
14
Hinweis: dtmuss in UTC sein (nicht lokal). Siehe ähnliche Antwort mit Python 2.6 / 3-Unterstützung
jfs
7
Erwähnenswert ist, dass Sie, wenn Sie nur einen echten Unix-Zeitstempel wie hier definiert möchten, en.wikipedia.org/wiki/Unix_time (und daher nur die Funktion unix_time aus dieser Antwort verwenden) delta.total_seconds () mit int to umschließen sollten Vermeiden Sie es, mit einem Float zu
enden
1
Epoche berechnet mit utcfromtimestamp(0) kann nur dann einen 'tz'-Offset verursachen, wenn' tz 'nicht 0 ist. Dies liegt daran, dass dt in dt- epoch' tz 'berechnet wurde, wobei die Epoche die UTC-Zeit ist. Der beste Weg, um die Epoche zu berechnen, epoch = datetime.datetime(1970, 1, 1)ist die Berücksichtigung der Zeitzone.
Ahj
35
Warum oh warum gibt datetime.utcfromtimestamp(0)eine Datumszeit ohne tzinfo zurück? Es ist genau dort im Methodennamen utc fromtimestamp. Um es nicht naiv zu machen, muss ich so etwas tun datetime.utcfromtimestamp(0).replace(tzinfo=pytz.UTC). Dies ist notwendig, wenn dtdie Zeitzone bekannt ist, sonst erhalten SieTypeError: can't subtract offset-naive and offset-aware datetimes
FGreg
170

In Python 3.3 wurde eine neue Methode hinzugefügt timestamp:

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

Ihre Frage ergab, dass Sie Millisekunden benötigen, die Sie wie folgt erhalten können:

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

Wenn Sie timestampein naives datetime-Objekt verwenden, wird davon ausgegangen, dass es sich in der lokalen Zeitzone befindet. Verwenden Sie zeitzonenabhängige datetime-Objekte, wenn dies nicht beabsichtigt ist.

Eshizhan
quelle
28
Hinweis: Bei der .timestamp()Methode wird davon ausgegangen, dass sich eine naive Eingabedatenzeit in der lokalen Zeitzone befindet (und die lokale Zeit möglicherweise nicht eindeutig ist). Wenn es in UTC ist, verwenden Sie dt.replace(tzinfo=timezone.utc).timestamp()stattdessen .
JFS
11
datetime.timestamp () gibt Epochensekunden als Float zurück. So erhalten Sie Millisekunden: int (datetime.timestamp () * 1000)
Solar.gy
9
Diese Antwort ist kein kopierfähiges und einfügbares Beispiel im Sinne der unmenschlichen Dokumente unter docs.python.org/3/library/… - dies ist: datetime.datetime.timestamp(datetime.datetime.now())
MarkHu
3
In 3.6 (mindestens) geht datetime.timestamp () davon aus, dass eine zeitzonennaive (tzinfo = None) datetime in UTC liegt. Also immer besser, wenn Sie Ihre Zeitzone eingestellt haben: datetime.datetime.now(pytz.timezone('Europe/Paris')).timestamp() == datetime.datetime.now(pytz.utc).timestamp() == datetime.datetime.utcnow().timestamp()aber nicht (immer) gleich datetime.datetime.now().timestamp()(diese letzte ist nur gleich dem Rest, wenn der lokale tz UTC ist ...)
Bluu
1
Für Ihr Interesse ist das Gegenteil] 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

Oder die Hilfe des Zeitmoduls (und ohne Datumsformatierung):

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

Beantwortet mit Hilfe von: http://pleac.sourceforge.net/pleac_python/datesandtimes.html

Dokumentation:

miku
quelle
6
Übrigens gibt strftime ("% s") eine leere Zeichenfolge für mich zurück. Der zweite Weg funktioniert gut.
Pavel Vlasov
23
Hat
6
'% s' wird von Python nicht unterstützt, z. B. fehlt es unter Windows. .timetuple()gibt tm_isdst=-1es zwingt mktime()zu raten. Während der Sommerzeit kann es zu falschen Vermutungen kommen (50% Fehlerwahrscheinlichkeit +/- Stunde). Beide '% s' und verwenden mktime()möglicherweise den falschen utc-Offset für Daten aus der Vergangenheit. Sie benötigen eine historische Zeitzonen-Datenbank, wie sie vom pytzModul bereitgestellt wird , um die Ortszeit zuverlässig in einen POSIX-Zeitstempel umzuwandeln (es sei denn, das Betriebssystem stellt bereits eine solche Datenbank bereit)
jfs
1
time.mktime(ts.timetuple())Dabei ist ts das Datum / Uhrzeit-Objekt von Python
suhailvs
1
@suhail: lies meinen Kommentar oben über mktime/timetuple. Außerdem werden timetuple()Sekundenbruchteile entfernt, und der Punkt der Frage besteht darin, den Zeitstempel mit Millisekundengenauigkeit zu erhalten.
JFS
13

So mache ich es:

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
quelle
2
@JFSebastian Danke für das Heads Up! in der Tat wird kein dst berücksichtigt. Wenn sich Ihr Server anstelle von UTC in der Ortszeit befindet, macht dies einen Unterschied. Ich habe (noch) keinen zwingenden Grund gefunden, Server in etwas anderem als UTC einzustellen. Mein Moto ist "UTC schreiben, Ortszeit lesen", damit Sie immer wissen, wo Sie sich aufhalten ...
estani
2
Sie können immer calendar.timegm anstelle von mktime verwenden, um das Problem zu vermeiden, dass mktime versucht, die Zeitzone zu erraten.
Decko
13

Empfehlungen aus den Python 2.7-Dokumenten für das timeModul

Konvertieren zwischen Zeitdarstellungen

Ankur Agarwal
quelle
@ChristopherBull Teilen Sie einfach die Anzahl der Millisekunden durch 1000, um auf Sekunden zu kommen
Jonas
5
Du hast es falsch verstanden und falsch verstanden. In den oben genannten Funktionen sind alle Sekunden verfügbar. Sie können es in Millisekunden konvertieren, aber es wäre die Genauigkeit einer Sekunde.
Christopher Bull
1
Diese Antwort verwendet das timeModul, aber das OP fragt nach dem datetimeModul. FWIW, die einfachste aktuelle Epoche istint(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
quelle
timegm()funktioniert nur mit utc zeit. Es wird nicht verwendet, tm_isdstdaher könnten Sie utcnow.timetuple()stattdessen verwenden utcnow.utctimetuple(). Hinweis: Die Verwendung naive_local_datetime.utctimetuple()wäre hier falsch. Die Ortszeit wird nicht in utc übersetzt. Auch timetuple()Streifen von Sekundenbruchteilen aus dem Ergebnis nennen (ob es wichtig ist, hängt von der Anwendung). Auch die Frage fragt nach * Milli * Sekunden, nicht Sekunden
jfs
Ich bevorzuge die Verwendung von utcnow () und utctimetuple (), um den Code absolut klar zu machen, dass Sie mit UTC zu tun haben (und auf diese Weise muss sich jeder, der ihn liest, nicht daran erinnern, dass timegm nur UTC ist). utctimetuple () impliziert keine Übersetzung für ein naives dttm-Objekt (daher wird das dttm mit utcnow () gestartet). Auch Frage erwähnt Sekunden oder Millisekunden.
Corford
Hinweis: hätte im letzten Kommentar sagen sollen, dass ich die Frage so gelesen habe, dass er Sekunden oder Millisekunden wollte (wahrscheinlich mein Fehler). Für Millis multiplizieren Sie einfach mit 1000 (wie die Antwort mit der höchsten Punktzahl nahelegt).
Corford
utctimetuple()Streifen Bruchteile einer Sekunde. Das Multiplizieren mit 1000bringt sie nicht zurück.
JFS
1
Aufgrund der Art und Weise, wie das OP diese Frage gestellt hat, ist unklar, was genau er / sie wollte (dh ein echter Unix-Zeitstempel oder ein Zeitstempel mit Millisekundengenauigkeit). Unabhängig davon wurden beide Fragen bereits an anderer Stelle gestellt und beantwortet. Trotzdem denke ich, dass die Antworten hier die schnellsten und saubersten sind, damit die Leute die verschiedenen Lösungen für das Problem gut veranschaulichen können.
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

Jinesh
quelle
3

Hier ist eine andere Form einer Lösung mit Normalisierung Ihres Zeitobjekts:

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
quelle
2

Ein bisschen Pandas-Code:

import pandas

def to_millis(dt):
    return int(pandas.to_datetime(dt).value / 1000000)
volhv
quelle
1
import time
seconds_since_epoch = time.mktime(your_datetime.timetuple()) * 1000
MattoTodd
quelle
9
Das ist falsch! Das Timupuple enthält keine Millisekunden, daher gibt mktime die Epoche nicht mit Millisekundenauflösung zurück. Es ist in diesem Fall nutzlos.
Wang
@ Wang - Sie sind richtig, Sir, dies gibt nicht Millis zurück, nur Sekunden
MattoTodd
1
Wenn Sie jedoch entfernen * 1000, erhalten Sie seconds_since_epoch. Diese Antwort zu verbessern, weil mir Millisekunden momentan egal sind.
Michael Scheper
0

Hier ist eine Funktion, die ich basierend auf der obigen Antwort gemacht habe

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

Sie können den zurückgegebenen Wert wie folgt umbrechen: str (int (res)) Um ihn ohne einen Dezimalwert zurückzugeben, der als Zeichenfolge verwendet werden soll, oder nur int (ohne str)

Gil Allen
quelle
-14

Diese andere Lösung für verdeckte Datums- und Uhrzeitangaben zu 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
quelle
2
Frage ist über Python-Sprache
Stéphane