web-dev-qa-db-de.com

Python: Wie bekomme ich einen Wert von datetime.today (), der "timezone aware" ist?

Ich versuche, einen Datumswert vom Wert von datetime.today() abzuziehen, um zu berechnen, wie lange etwas vorhin war. Aber es beschwert sich:

TypeError: can't subtract offset-naive and offset-aware datetimes

Der Wert datetime.today() scheint nicht "zeitzonenbewusst" zu sein, während mein anderer Datumswert ist. Wie erhalte ich einen Wert von datetime.today(), der die Zeitzone kennt? Im Moment gibt es mir die Zeit in der Ortszeit, die zufällig PST ist, d. H. UTC-8 Stunden. Gibt es im schlimmsten Fall eine Möglichkeit, einen Zeitzonenwert manuell in das von datetime.today() zurückgegebene datetime-Objekt einzugeben und auf UTC-8 zu setzen? Die ideale Lösung wäre natürlich, die Zeitzone automatisch zu kennen.

226
mindthief

In der Standardbibliothek gibt es keine plattformübergreifende Methode zum Erstellen von Zeitzonen ohne die Erstellung einer eigenen Zeitzonenklasse.

Unter Windows gibt es win32timezone.utcnow(), aber das ist Teil von pywin32. Ich würde eher vorschlagen, die pytz-Bibliothek zu verwenden, die eine ständig aktualisierte Datenbank der meisten Zeitzonen hat.

Die Arbeit mit lokalen Zeitzonen kann sehr schwierig sein (siehe "Weiterführende Links" weiter unten). Daher möchten Sie möglicherweise UTC in Ihrer gesamten Anwendung verwenden, insbesondere für arithmetische Operationen, wie die Differenz zwischen zwei Zeitpunkten.

Sie können das aktuelle Datum/die Uhrzeit wie folgt erhalten:

import pytz
from datetime import datetime
datetime.utcnow().replace(tzinfo=pytz.utc)

Beachten Sie, dass datetime.today() und datetime.now() die Zeit local und nicht die UTC-Zeit zurückgeben. Die Anwendung von .replace(tzinfo=pytz.utc) auf sie wäre daher nicht korrekt.

Ein weiterer schöner Weg, es zu tun, ist:

datetime.now(pytz.utc)

das ist etwas kürzer und macht das gleiche.


Weitere Lektüre/Beobachtung, warum in vielen Fällen UTC bevorzugt wird:

290
AndiDog

Aktuelle Uhrzeit in einer bestimmten Zeitzone abrufen:

import datetime
import pytz
my_date = datetime.datetime.now(pytz.timezone('US/Pacific'))
80
philfreo

In Python 3 macht es die Standardbibliothek viel einfacher, UTC als Zeitzone anzugeben:

>>> import datetime
>>> datetime.datetime.now(datetime.timezone.utc)
datetime.datetime(2016, 8, 26, 14, 34, 34, 74823, tzinfo=datetime.timezone.utc)

Wenn Sie eine Lösung suchen, die nur die Standardbibliothek verwendet und sowohl in Python 2 als auch in Python 3 funktioniert, siehe Antwort von J. F. Sebastien .

37
Flimm

Hier ist eine stdlib-Lösung, die auf Python 2 und 3 funktioniert:

from datetime import datetime

now = datetime.now(utc) # timezone-aware datetime.utcnow()
today = datetime(now.year, now.month, now.day, tzinfo=utc) # midnight

dabei ist today eine bewusste Datetime-Instanz, die den Beginn des Tages (Mitternacht) in UTC darstellt, und utc ist ein Tzinfo-Objekt ( Beispiel aus den Dokumenten ):

from datetime import tzinfo, timedelta

ZERO = timedelta(0)

class UTC(tzinfo):
    def utcoffset(self, dt):
        return ZERO

    def tzname(self, dt):
        return "UTC"

    def dst(self, dt):
        return ZERO

utc = UTC()

Verwandte: Leistungsvergleich von mehrere Möglichkeiten, um Mitternacht (Tagesbeginn) für eine bestimmte UTC-Zeit zu erhalten .
Hinweis: Es ist komplizierter, für eine Zeitzone mit einem nicht feststehenden Versatz der Utc Mitternacht zu erhalten.

16
jfs

Eine andere Methode zum Erstellen eines zeitzonenabhängigen Datumszeitobjekts, das die aktuelle Uhrzeit darstellt:

import datetime
import pytz

pytz.utc.localize( datetime.datetime.utcnow() )  
11
Dariusz Walczak

Wenn Sie Django verwenden, können Sie Datumsangaben festlegen (nur utc).

Kommentar folgende Zeile in settings.py:

USE_TZ = True
8
laffuste

pytz ist eine Python-Bibliothek, die genaue und plattformübergreifende Zeitzonenberechnungen mit Python 2.3 oder höher ermöglicht.

Mit der stdlib ist dies nicht möglich. 

Siehe eine ähnliche Frage zu SO .

6
user225312

Hier ist eine Möglichkeit, es mit der stdlib zu generieren:

import time
from datetime import datetime

FORMAT='%Y-%m-%dT%H:%M:%S%z'
date=datetime.strptime(time.strftime(FORMAT, time.localtime()),FORMAT)

date speichert das lokale Datum und den Offset von UTC, nicht das Datum in der UTC-Zeitzone. Sie können diese Lösung also verwenden, wenn Sie angeben müssen, in welcher Zeitzone das Datum in generiert wird. In diesem Beispiel und in meiner lokalen Zeitzone:

date
datetime.datetime(2017, 8, 1, 12, 15, 44, tzinfo=datetime.timezone(datetime.timedelta(0, 7200)))

date.tzname()
'UTC+02:00'

Der Schlüssel ist das Hinzufügen der %z-Direktive zur Repräsentation FORMAT, um den UTC-Versatz der generierten Zeitstruktur anzuzeigen. Andere Darstellungsformate können im datetime-Modul docs eingesehen werden.

Wenn Sie das Datum in der UTC-Zeitzone benötigen, können Sie time.localtime () durch time.gmtime () ersetzen.

date=datetime.strptime(time.strftime(FORMAT, time.gmtime()),FORMAT)

date    
datetime.datetime(2017, 8, 1, 10, 23, 51, tzinfo=datetime.timezone.utc)

date.tzname()
'UTC'

Bearbeiten

Dies funktioniert nur bei Python3. Die z-Direktive ist auf Python 2 _strptime.py-Code nicht verfügbar. _

5
jcazor

Warum wird dateutil nicht wie hier beschrieben verwendet: http://joelinoff.com/blog/?p=802

from dateutil.tz import tzlocal
# Get the current date/time with the timezone.
now = datetime.datetime.now(tzlocal())
4
G. Führ

Um ein Zeitzonen-bewusstes Datum in utc Zeitzone zu erhalten, reicht es aus, dass die Datumsabnahme funktioniert. 

Wenn Sie jedoch in Ihrer aktuellen Zeitzone ein Datum in der Zeitzone wünschen, ist tzlocal der richtige Weg:

from tzlocal import get_localzone  # pip install tzlocal
from datetime import datetime
datetime.now(get_localzone())

PS dateutil hat eine ähnliche Funktion (dateutil.tz.tzlocal). Aber trotz der Weitergabe des Namens hat er eine völlig andere Codebasis, die als notiert von J. F. Sebastian falsche Ergebnisse liefern kann.

1

Sie können eine lokale timezone mit datetime erstellen, indem Sie die Ausgabe eines time.strftime-Aufrufs analysieren, der die %z-Direktive (eingeführt in Python 3.3) verwendet, wie von jcazor angezeigt. Sie können diese timezone verwenden, um eine bewusste datetime-Instanz mit einem Einzeiler zu erstellen:

import time
from datetime import datetime

aware_local_now = datetime.now(
    tz=datetime.strptime(time.strftime("%z", time.localtime()), "%z").tzinfo)

print(aware_local_now)
2018-03-01 13:41:26.753644-08:00
1
Mihai Capotă

Wenn Sie die aktuelle Uhrzeit und das aktuelle Datum in Python erhalten, importieren Sie das Datum und die Uhrzeit. Nach dem Pytz-Paket in Python erhalten Sie das aktuelle Datum und die aktuelle Uhrzeit.

from datetime import datetime
import pytz
import time
str(datetime.strftime(datetime.now(pytz.utc),"%Y-%m-%d %H:%M:%S%t"))
0
jigar vagadiya

Ich füge diese Antwort als jemand hinzu, der häufig mit Nicht-UTC-Zeitzonen arbeitet.

Die einzige Zeitzone mit einer eigenen Methode ist timezone.utc. Sie können jedoch eine Zeitzone mit einem beliebigen UTC-Versatz verschieben, indem Sie timedelta & timezone verwenden und ihn mit .replace erzwingen.

In [1]: from datetime import datetime, timezone, timedelta

In [2]: def force_timezone(dt, utc_offset=0):
   ...:     return dt.replace(tzinfo=timezone(timedelta(hours=utc_offset)))
   ...:

In [3]: dt = datetime(2011,8,15,8,15,12,0)

In [4]: str(dt)
Out[4]: '2011-08-15 08:15:12'

In [5]: str(force_timezone(dt, -8))
Out[5]: '2011-08-15 08:15:12-08:00'

Die Verwendung von timezone(timedelta(hours=n)) als Zeitzone ist hier der Königsweg und es gibt viele andere nützliche Anwendungen.

0
tmck-code

Verwenden Sie die Zeitzone wie unten gezeigt, um das Datum und die Uhrzeit in einer Zeitzone anzuzeigen.

    from Django.utils import timezone
    today = timezone.now() 
0