Mit einer Mongoengine Document
, wenn ich eine DateTimeField
von Mongo laden, fehlt es tzinfo
. Unsere Anwendung nach Richtlinie möchte, dass alle Datumsangaben tzinfo
haben.Wie kann ich CodecOptions auf eine Mongoengine-Sammlung anwenden, um TZinfo zu erhalten?
Wenn ich auf Mongo speichere, weiß ich, dass Pymongo die richtige und vorhersagbare Sache in Zeitzonen tut; Wenn es naiv ist, wird es als UTC-Zeit gespeichert, wenn es eine Zeitzone hat, wird es in UTC konvertiert und dann als UTC-Zeit gespeichert. Alles gut bis jetzt.
Wenn ich lade, aber DateTimeField
gibt mir immer eine naive datetime
. Ich weiß, dass datetime
in UTC ist, also könnte ich die tzinfo
hinzufügen, wenn ich wollte, aber ich würde dies an Dutzenden von Orten in meiner Anwendung tun müssen, und es ist eine Garantie für zukünftige Zeitzone Bugs , es sei denn ich benutze ein benutzerdefinierter Feldtyp (siehe Beispiel unten).
Referenzieren: https://api.mongodb.com/python/current/examples/datetimes.html Ich weiß, dass Pymongo unterstützt die tzinfo
auf das Objekt, wie es aus der Datenbank ankommt. Ich weiß auch, dass ich das selbst machen kann, wie das folgende minimale Beispiel zeigt. Die DateTimeTZField
fügt tzinfo
in to_python
hinzu.
from datetime import datetime
from mongoengine import connect, Document, fields
from pytz import timezone
def utcnowTZ():
return datetime.utcnow().replace(tzinfo=timezone('UTF'))
class DateTimeTZField(fields.DateTimeField):
"""
This seems like a hack. I would like to use CodecOptions instead
"""
def to_python(self, value):
converted = super(DateTimeTZField, self).to_python(value)
return converted.replace(tzinfo=timezone('UTC'))
class Thing(Document):
dtTZ = DateTimeTZField(default=utcnowTZ)
dtXX = fields.DateTimeField(default=utcnowTZ)
connect(host="mongodb://localhost/datetimewithtz")
Thing.objects().delete()
t1 = Thing()
print '%r.dtXX (default): %s' % (t1, t1.dtXX)
print '%r.dtTZ (default): %s' % (t1, t1.dtTZ)
t1.save()
print 'saved %r' % t1.id; print
t1 = Thing.objects(id=t1.id).first()
print 'reloaded %r' % t1.id
print '%r.dtXX (loaded): %s' % (t1, t1.dtXX)
print '%r.dtTZ (loaded): %s' % (t1, t1.dtTZ)
Ohne Datetimefield während meiner Anwendung zu ersetzen, ist es eine Möglichkeit, BSON CodecOptions verwenden auf diese global für alle DateTimeFields machen gelten: wenn aus der Datenbank geladen, sollten sie Tzinfo angeschlossen haben?
Danke für die nachdenkliche Antwort, ich komme wieder, sobald ich das versucht habe. Ich werde CodecOptions instanziieren (tz_aware = True), lassen Sie mich wissen, wenn das nicht stimmt. – Cory