Ich arbeite mit Datumsangaben in Python und muss sie in UTC-Zeitstempel konvertieren, um sie in Javascript zu verwenden. in Javascript zu verwenden. Der folgende Code funktioniert nicht:
>>> d = datetime.date(2011,01,01)
>>> datetime.datetime.utcfromtimestamp(time.mktime(d.timetuple()))
datetime.datetime(2010, 12, 31, 23, 0)
Die Konvertierung des Datumsobjekts in datetime hilft auch nicht. Ich habe das Beispiel unter diesem Link ausprobiert, aber:
from pytz import utc, timezone
from datetime import datetime
from time import mktime
input_date = datetime(year=2011, month=1, day=15)
und jetzt entweder:
mktime(utc.localize(input_date).utctimetuple())
oder
mktime(timezone('US/Eastern').localize(input_date).utctimetuple())
funktioniert.
Also allgemeine Frage: wie kann ich ein Datum in Sekunden seit der Epoche nach UTC umrechnen lassen?
Wenn d = date(2011, 1, 1)
in UTC ist:
>>> from datetime import datetime, date
>>> import calendar
>>> timestamp1 = calendar.timegm(d.timetuple())
>>> datetime.utcfromtimestamp(timestamp1)
datetime.datetime(2011, 1, 1, 0, 0)
Wenn d
in der lokalen Zeitzone ist:
>>> import time
>>> timestamp2 = time.mktime(d.timetuple()) # DO NOT USE IT WITH UTC DATE
>>> datetime.fromtimestamp(timestamp2)
datetime.datetime(2011, 1, 1, 0, 0)
Zeitstempel1" und "Zeitstempel2" können sich unterscheiden, wenn Mitternacht in der lokalen Zeitzone nicht dieselbe Zeitinstanz ist wie Mitternacht in UTC.
mktime()
kann ein falsches Ergebnis liefern, wenn d
einer mehrdeutigen Ortszeit (z.B. während der Sommerzeitumstellung) entspricht oder wenn d
ein vergangenes (zukünftiges) Datum ist, bei dem der utc-Offset anders gewesen sein könnte und das C mktime()
keinen Zugriff auf die tz-Datenbank auf der gegebenen Plattform hat. Sie könnten das Modul pytz
verwenden (z.B. über tzlocal.get_localzone()
), um Zugriff auf die tz-Datenbank auf allen Plattformen zu erhalten. Außerdem kann utcfromtimestamp()
fehlschlagen und mktime()
kann einen Nicht-POSIX-Zeitstempel zurückgeben, wenn "right"
timezone verwendet wird.
Konvertierung von datetime.date
-Objekten, die das Datum in UTC darstellen, ohne calendar.timegm()
:
DAY = 24*60*60 # POSIX day in seconds (exact value)
timestamp = (utc_date.toordinal() - date(1970, 1, 1).toordinal()) * DAY
timestamp = (utc_date - date(1970, 1, 1)).days * DAY
So konvertieren Sie das Objekt datetime.datetime
(nicht datetime.date
), das bereits die Zeit in UTC darstellt, in den entsprechenden POSIX-Zeitstempel (ein float
).
from datetime import timezone
timestamp = dt.replace(tzinfo=timezone.utc).timestamp()
Hinweis: Es ist notwendig, timezone.utc
explizit anzugeben, da sonst .timestamp()
annimmt, dass Ihr naives datetime-Objekt in der lokalen Zeitzone ist.
Aus den Unterlagen für [datetime.utcfromtimestamp()
] (http://docs.python.org/dev/library/datetime#datetime.datetime.utcfromtimestamp):
Es gibt keine Methode, um den Zeitstempel aus einer datetime-Instanz zu erhalten, aber der POSIX-Zeitstempel, der einer datetime-Instanz dt entspricht, kann leicht wie folgt berechnet werden. Für ein naives dt:
timestamp = (dt - datetime(1970, 1, 1)) / timedelta(seconds=1)
Und für einen bewussten dt:
timestamp = (dt - datetime(1970,1,1, tzinfo=timezone.utc)) / timedelta(seconds=1)
Interessante Lektüre: Epoch time vs. time of day über den Unterschied zwischen Wie spät ist es? und Wie viele Sekunden sind verstrichen?
Siehe auch: datetime benötigt eine "epoch" Methode
Um den obigen Code für Python 2 anzupassen:
timestamp = (dt - datetime(1970, 1, 1)).total_seconds()
wobei timedelta.total_seconds()
äquivalent ist zu (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6
, berechnet mit aktivierter echter Division.
from __future__ import division
from datetime import datetime, timedelta
def totimestamp(dt, epoch=datetime(1970,1,1)):
td = dt - epoch
# return td.total_seconds()
return (td.microseconds + (td.seconds + td.days * 86400) * 10**6) / 10**6
now = datetime.utcnow()
print now
print totimestamp(now)
Vorsicht vor Fließkomma-Problemen.
2012-01-08 15:34:10.022403
1326036850.02
datetime
-Objekts in einen POSIX-Zeitstempelassert dt.tzinfo is not None and dt.utcoffset() is not None
timestamp = dt.timestamp() # Python 3.3+
Unter Python 3:
from datetime import datetime, timedelta, timezone
epoch = datetime(1970, 1, 1, tzinfo=timezone.utc)
timestamp = (dt - epoch) / timedelta(seconds=1)
integer_timestamp = (dt - epoch) // timedelta(seconds=1)
Unter Python 2:
# utc time = local time - utc offset
utc_naive = dt.replace(tzinfo=None) - dt.utcoffset()
timestamp = (utc_naive - datetime(1970, 1, 1)).total_seconds()
Annahme 1: Sie versuchen, ein Datum in einen Zeitstempel zu konvertieren. Da ein Datum jedoch einen Zeitraum von 24 Stunden abdeckt, gibt es keinen einzigen Zeitstempel, der dieses Datum darstellt. Ich gehe davon aus, dass Sie den Zeitstempel dieses Datums um Mitternacht (00:00:00.000) darstellen wollen.
Annahme 2: Das von Ihnen dargestellte Datum ist nicht mit einer bestimmten Zeitzone verbunden, Sie möchten jedoch den Abstand zu einer bestimmten Zeitzone (UTC) bestimmen. Ohne zu wissen, in welcher Zeitzone das Datum liegt, ist es nicht möglich, einen Zeitstempel für eine bestimmte Zeitzone zu berechnen. Ich gehe davon aus, dass Sie das Datum so behandeln wollen, als befände es sich in der lokalen Systemzeitzone.
Zunächst können Sie die Datumsinstanz in ein Tupel umwandeln, das die verschiedenen Zeitkomponenten repräsentiert, indem Sie das Element timetuple()
verwenden:
dtt = d.timetuple() # time.struct_time(tm_year=2011, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=1, tm_isdst=-1)
Dieses Tupel können Sie dann mit time.mktime
in einen Zeitstempel umwandeln:
ts = time.mktime(dtt) # 1293868800.0
Sie können diese Methode überprüfen, indem Sie sie mit der Epochenzeit selbst (1970-01-01) testen. In diesem Fall sollte die Funktion den Zeitzonen-Offset für die lokale Zeitzone an diesem Datum zurückgeben:
d = datetime.date(1970,1,1)
dtt = d.timetuple() # time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=1, tm_isdst=-1)
ts = time.mktime(dtt) # 28800.0
28800.0
ist 8 Stunden, was für die pazifische Zeitzone (in der ich mich befinde) korrekt wäre.
Ein vollständiger Zeitstrang enthält:
[+HHMM oder -HHMM]
Zum Beispiel:
1970-01-01 06:00:00 +0500
== 1970-01-01 01:00:00 +0000
== UNIX-Zeitstempel:3600
$ python3
>>> from datetime import datetime
>>> from calendar import timegm
>>> tm = '1970-01-01 06:00:00 +0500'
>>> fmt = '%Y-%m-%d %H:%M:%S %z'
>>> timegm(datetime.strptime(tm, fmt).utctimetuple())
3600
Anmerkung:
Der UNIX-Zeitstempel
ist eine Fließkommazahl, die in Sekunden seit der Epoche in UTC ausgedrückt wird.
Bearbeiten:
$ python3
>>> from datetime import datetime, timezone, timedelta
>>> from calendar import timegm
>>> dt = datetime(1970, 1, 1, 6, 0)
>>> tz = timezone(timedelta(hours=5))
>>> timegm(dt.replace(tzinfo=tz).utctimetuple())
3600