Wie konvertiert man in Python ein "datetime" -Objekt in Sekunden?

226

Entschuldigung für die einfache Frage ... Ich bin neu in Python ... Ich habe mich umgesehen und nichts scheint zu funktionieren.

Ich habe eine Reihe von Datums- / Uhrzeitobjekten und möchte die Anzahl der Sekunden seit einer festgelegten Zeit in der Vergangenheit für jedes Objekt berechnen (z. B. seit dem 1. Januar 1970).

import datetime
t = datetime.datetime(2009, 10, 21, 0, 0)

Dies scheint nur zwischen Daten zu unterscheiden, die unterschiedliche Tage haben:

t.toordinal()

Jede Hilfe wird sehr geschätzt.

Nathan Lippi
quelle
2
Ich würde wahrscheinlich beide seit der Epoche in S konvertieren und von dort aus gehen: int(t.timestamp())
Nerdwaller
Für die entgegengesetzte Operation gehen Sie hier: Konvertieren Sie Sekunden seit der Epoche in ein Datetime-Objekt
Trevor Boyd Smith

Antworten:

233

Für das Sonderdatum 1. Januar 1970 gibt es mehrere Möglichkeiten.

Für jedes andere Startdatum müssen Sie die Differenz zwischen den beiden Daten in Sekunden ermitteln. Das Subtrahieren von zwei Daten ergibt ein timedeltaObjekt, das ab Python 2.7 eine total_seconds()Funktion hat.

>>> (t-datetime.datetime(1970,1,1)).total_seconds()
1256083200.0

Das Startdatum wird normalerweise in UTC angegeben. Für korrekte Ergebnisse sollte die datetimeEingabe in diese Formel auch in UTC erfolgen. Wenn Sie datetimenoch nicht in UTC sind, müssen Sie es konvertieren, bevor Sie es verwenden, oder eine tzinfoKlasse mit dem richtigen Offset anhängen .

Wie in den Kommentaren erwähnt, benötigen Sie am Startdatum auch eine, wenn Sie eine tzinfoan Ihre angehängt haben. datetimeAndernfalls schlägt die Subtraktion fehl. Für das obige Beispiel würde ich hinzufügen, tzinfo=pytz.utcwenn Python 2 oder tzinfo=timezone.utcPython 3 verwendet wird.

Mark Ransom
quelle
1
Python warnt mich jetzt: "TypeError: Offset-naive und Offset-fähige Daten können nicht subtrahiert werden." Was ist die beste Lösung, um das zu beheben?
Aaron Ash
2
@Charybdis, versuchen Sie es datetime.datetime(1970,1,1,tzinfo=pytz.utc).
Mark Ransom
9
Erwägen Sie die Verwendung von: datetime.datetime.utcfromtimestamp(0) Ich habe dies verwendet, um die "Epoche" leicht zu bekommen. Beachten Sie, dass die Epoche nicht immer auf allen Systemen gleich ist.
DA
3
Seien Sie hier sehr vorsichtig mit Zeitzonen. Ich bin bei UTC + 2, was bedeutet, dass die Ausgabe von time.time()und datetime.now() - datetime(1970, 1, 1)um 7200 Sekunden abweicht. Eher benutzen (t - datetime.datetime.fromtimestamp(0)).total_seconds(). Sie nicht verwenden , utcfromtimestamp(0)wenn Sie ein Datetime in Ihrer lokalen Zeitzone konvertieren möchten.
Carl
2
@DA: Python unterstützt keine Nicht-POSIX-Epochen . Alle Systeme, auf denen Python funktioniert, verwenden dieselbe Epoche: 1970-01-01 00:00:00 UTC
jfs
130

So erhalten Sie die Unix-Zeit (Sekunden seit dem 1. Januar 1970):

>>> import datetime, time
>>> t = datetime.datetime(2011, 10, 21, 0, 0)
>>> time.mktime(t.timetuple())
1319148000.0
Mark Byers
quelle
22
Seien Sie vorsichtig, wenn Sie time.mktime als Ausdruck der Ortszeit und plattformabhängig verwenden
Shih-Wen Su
7
Sei in der Tat vorsichtig. Es hat mich in den Arsch gebissen
Arg
Es wird davon ausgegangen, dass dies teine Ortszeit ist. Der UTC-Offset für die lokale Zeitzone war in der Vergangenheit möglicherweise anders. Wenn mktime()(C-Bibliothek) auf einer bestimmten Plattform keinen Zugriff auf historische Zeitzonendaten hat, kann dies fehlschlagen (dies pytzist eine tragbare Methode für den Zugriff auf die tz-Datenbank). Außerdem kann die Ortszeit mehrdeutig sein, z. B. während der Sommerzeitübergänge - Sie benötigen zusätzliche Informationen, um eindeutig zu sein, z. B. wenn Sie wissen, dass aufeinanderfolgende Datums- / Zeitwerte in einer Protokolldatei ansteigen sollten
jfs
1
Seien Sie vorsichtig, wenn Sie dies in Zeiten von Sekundenbruchteilen verwenden. time.mktime(datetime.datetime(2019, 8, 3, 4, 5, 6, 912000).timetuple())führt dazu 1564819506.0, dass die Millisekunden stillschweigend fallen gelassen werden, aber datetime.datetime(2019, 8, 3, 4, 5, 6, 912000).timestamp()(Andrzej Pronobis 'Antwort) ergibt 1564819506.912das erwartete Ergebnis.
Alex
128

Ab Python 3.3 wird dies mit der datetime.timestamp()Methode sehr einfach . Dies ist natürlich nur dann nützlich, wenn Sie die Anzahl der Sekunden ab dem 01.01.1970 UTC benötigen.

from datetime import datetime
dt = datetime.today()  # Get timezone naive now
seconds = dt.timestamp()

Der Rückgabewert ist ein Float, der gerade Bruchteile einer Sekunde darstellt. Wenn die Datums- und Uhrzeitzeitzone naiv ist (wie im obigen Beispiel), wird davon ausgegangen, dass das Datums- / Uhrzeitobjekt die Ortszeit darstellt, dh die Anzahl der Sekunden von der aktuellen Uhrzeit an Ihrem Standort bis zum 01.01.1970 UTC.

Andrzej Pronobis
quelle
3
Wer auch immer dies abgelehnt hat, können Sie bitte erklären, warum?
Andrzej Pronobis
5
Ich nehme an, die Abwertung ist auf das Python-2.7-Tag in der Frage zurückzuführen (es ist nur eine Vermutung).
JFS
3
Dies sollte die akzeptierte Antwort sein / die akzeptierte Antwort sollte entsprechend aktualisiert werden.
DreamFlasher
11
Zeit für ein Upgrade, denke ich;)
DreamFlasher
ist es möglich, diese Entfernung von einem anderen Startdatum zu berechnen? (Ich möchte das Datum
1970-01-01 ändern
29

Vielleicht nicht zum Thema: UNIX / POSIX-Zeit von datetime abrufen und zurückkonvertieren:

>>> import datetime, time
>>> dt = datetime.datetime(2011, 10, 21, 0, 0)
>>> s = time.mktime(dt.timetuple())
>>> s
1319148000.0

# and back
>>> datetime.datetime.fromtimestamp(s)
datetime.datetime(2011, 10, 21, 0, 0)

Beachten Sie, dass unterschiedliche Zeitzonen Auswirkungen auf die Ergebnisse haben, z. B. meine aktuelle TZ / DST-Rendite:

>>>  time.mktime(datetime.datetime(1970, 1, 1, 0, 0).timetuple())
-3600 # -1h

Daher sollte eine Normalisierung auf UTC in Betracht gezogen werden, indem UTC-Versionen der Funktionen verwendet werden.

Beachten Sie, dass das vorherige Ergebnis verwendet werden kann, um den UTC-Versatz Ihrer aktuellen Zeitzone zu berechnen. In diesem Beispiel ist dies + 1h, dh UTC + 0100.

Verweise:

Robert Lujo
quelle
mktime()kann fehlschlagen . Im Allgemeinen müssen Sie pytzdie Ortszeit in utc konvertieren, um den POSIX-Zeitstempel zu erhalten.
JFS
calendar.timegm () scheint die utc-Version von time.mktime () zu sein
frankster
27

int (t.strftime("%s")) funktioniert auch

dan3
quelle
1
Funktioniert für mich in Python 2.7 mit import datetime; t = datetime.datetime(2011, 10, 21, 0, 0)(wie von OP angegeben). Aber ich bezweifle wirklich, dass% s ein kürzlich hinzugefügtes Zeitformat ist.
Dan3
1
@ dan3: falsch. %swird nicht unterstützt (es kann auf einigen Plattformen funktionieren, wenn tf ein naives datetime-Objekt ist, das die lokale Zeit darstellt, und wenn die lokale C-Bibliothek Zugriff auf die tz-Datenbank hat, andernfalls kann das Ergebnis falsch sein). Benutze es nicht.
JFS
%sist nirgendwo dokumentiert. Ich habe es in echtem Code gesät und mich gefragt, was das ist und in der Dokumentation nachgesehen und es gibt keine %s. Es gibt nur mit großem S nur für die Sekunden.
VStoykov
13

aus den Python-Dokumenten:

timedelta.total_seconds()

Gibt die Gesamtzahl der Sekunden zurück, die in der Dauer enthalten sind. Gleichwertig

(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6

berechnet mit aktivierter wahrer Division.

Beachten Sie, dass diese Methode bei sehr großen Zeitintervallen (auf den meisten Plattformen länger als 270 Jahre) an Mikrosekundengenauigkeit verliert.

Diese Funktionalität ist neu in Version 2.7.

Michael
quelle
1
Es gibt ein kleines Problem bei der Berechnung, es muss 10 6 statt 10 * 6 sein ... td.microseconds + (td.seconds + td.days * 24 * 3600) * 10 6) / 10 ** 6
sdu
@sdu toller Fang - das doppelte Sternchen ist in meiner Antwort, aber Stackoverflow verbraucht es, Versuche zu korrigieren, ermutigen nur den Text.
Michael
2

So konvertieren Sie ein Datum / Uhrzeit-Objekt, das die Zeit in UTC darstellt, in einen POSIX-Zeitstempel :

from datetime import timezone

seconds_since_epoch = utc_time.replace(tzinfo=timezone.utc).timestamp()

So konvertieren Sie ein Datum / Uhrzeit-Objekt, das die Zeit in der lokalen Zeitzone darstellt, in einen POSIX-Zeitstempel:

import tzlocal # $ pip install tzlocal

local_timezone = tzlocal.get_localzone()
seconds_since_epoch = local_timezone.localize(local_time, is_dst=None).timestamp()

Siehe Wie konvertiere ich die Ortszeit in Python in UTC? Wenn die tz-Datenbank auf einer bestimmten Plattform verfügbar ist; Möglicherweise funktioniert nur eine stdlib-Lösung .

Folgen Sie den Links, wenn Sie Lösungen für <3.3Python-Versionen benötigen .

jfs
quelle
1

Ich habe den Kalender.timegm der Standardbibliothek ausprobiert und es funktioniert ganz gut:

# convert a datetime to milliseconds since Epoch
def datetime_to_utc_milliseconds(aDateTime):
    return int(calendar.timegm(aDateTime.timetuple())*1000)

Ref: https://docs.python.org/2/library/calendar.html#calendar.timegm

Shaohong Li
quelle
es streift Sekundenbruchteile ab. Es wird davon aDateTime
ausgegangen,