500 Stimmen

Man kann offset-naive und offset-bewusste Zeitpunkte nicht subtrahieren

Ich habe eine zeitzonenbewusste timestamptz Feld in PostgreSQL. Wenn ich Daten aus der Tabelle ziehe, möchte ich die aktuelle Zeit subtrahieren, um das Alter zu ermitteln.

Das Problem, das ich habe, ist, dass beide datetime.datetime.now() y datetime.datetime.utcnow() scheinen Zeitzonen-unkorrekte Zeitstempel zurückzugeben, was dazu führt, dass ich diesen Fehler erhalte:

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

Gibt es eine Möglichkeit, dies zu vermeiden (vorzugsweise ohne Verwendung eines Moduls eines Drittanbieters).

EDIT: Vielen Dank für die Vorschläge, jedoch versucht, die Zeitzone anzupassen scheint, mir Fehler zu geben.. so ich bin nur gehen, um Zeitzone nicht bewusst Zeitstempel in PG und immer einfügen mit verwenden:

NOW() AT TIME ZONE 'UTC'

Auf diese Weise sind alle meine Zeitstempel standardmäßig UTC (auch wenn es lästiger ist, dies zu tun).

471voto

phillc Punkte 6531

Haben Sie versucht, die Zeitzonenerkennung zu entfernen?

von http://pytz.sourceforge.net/

naive = dt.replace(tzinfo=None)

möglicherweise auch die Zeitzonenumrechnung hinzufügen müssen.

edit: Bitte beachten Sie das Alter dieser Antwort. Eine Antwort, die das HINZUFÜGEN der Zeitzoneninformation beinhaltet, anstatt sie in Python 3 zu entfernen, finden Sie unten. https://stackoverflow.com/a/25662061/93380

417voto

jfs Punkte 370717

Die richtige Lösung ist hinzufügen. die Zeitzoneninformation, z.B. um die aktuelle Zeit als aware datetime-Objekt in Python 3 zu erhalten:

from datetime import datetime, timezone

now = datetime.now(timezone.utc)

In älteren Python-Versionen konnten Sie die utc tzinfo-Objekt selbst zu erstellen (Beispiel aus den datetime-Dokumenten):

from datetime import tzinfo, timedelta, datetime

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

entonces:

now = datetime.now(utc)

79voto

sage Punkte 4490

Ich weiß, dass einige Leute Django speziell als Schnittstelle verwenden, um diese Art der Datenbankinteraktion zu abstrahieren. Django bietet Hilfsprogramme, die für diese Zwecke verwendet werden können:

from django.utils import timezone
now_aware = timezone.now()

Sie müssen eine grundlegende Infrastruktur für Django-Einstellungen einrichten, auch wenn Sie nur diese Art von Schnittstelle verwenden (in den Einstellungen müssen Sie die USE_TZ=True um eine bewusste Zeitangabe zu erhalten).

Das allein ist wahrscheinlich nicht annähernd genug, um Sie zu motivieren, Django als Schnittstelle zu verwenden, aber es gibt viele andere Vorteile. Andererseits, wenn Sie hierher gestolpert sind, weil Sie Ihre Django-Anwendung verpfuscht haben (so wie ich), dann hilft das vielleicht...

49voto

ePi272314 Punkte 11235

Dies ist eine sehr einfache und klare Lösung
Zwei Codezeilen

# First we obtain de timezone info o some datatime variable    

tz_info = your_timezone_aware_variable.tzinfo

# Now we can subtract two variables using the same time zone info
# For instance
# Lets obtain the Now() datetime but for the tz_info we got before

diff = datetime.datetime.now(tz_info)-your_timezone_aware_variable

Schlussfolgerung: Sie müssen Ihre Datetime-Variablen mit der gleichen Zeitangabe verwalten

26voto

JeffCharter Punkte 1263

Sie brauchen nichts außerhalb der Standardbibliotheken

datetime.datetime.now().astimezone()

Wenn Sie nur die Zeitzone ersetzen, wird die Zeit nicht angepasst. Wenn Ihr System bereits UTC ist, ist .replace(tz='UTC') in Ordnung.

>>> x=datetime.datetime.now()
datetime.datetime(2020, 11, 16, 7, 57, 5, 364576)

>>> print(x)
2020-11-16 07:57:05.364576

>>> print(x.astimezone()) 
2020-11-16 07:57:05.364576-07:00

>>> print(x.replace(tzinfo=datetime.timezone.utc)) # wrong
2020-11-16 07:57:05.364576+00:00

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X