使用mongoengine Document
,当我从mongo加载DateTimeField
时,它缺少tzinfo
。根据政策,我们的申请要求所有日期时间都具有tzinfo
。
当我保存到mongo时,我知道pymongo会在时区执行正确且可预测的操作;如果天真,则将其存储为UTC时间;如果具有时区,则将其转换为UTC,然后将其存储为UTC时间。到目前为止一切都很好。
但是,当我加载时,DateTimeField
总是给我天真的datetime
。我知道这个datetime
是UTC,所以我可以根据需要添加tzinfo
,但是我必须在应用程序的数十个位置中执行此操作,这是将来时区错误的保证,除非我使用自定义字段类型(请参见下面的示例)。
引用:https://api.mongodb.com/python/current/examples/datetimes.html我知道pymongo支持将tzinfo
放在从数据库到达的对象上。我也知道我可以自己做,如下面的最小示例所示。 DateTimeTZField
在tzinfo
中添加to_python
。
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)
无需在整个应用程序中替换DateTimeField,是否可以使用bson CodecOptions使其全局应用于所有DateTimeFields:从数据库加载时,它们应该附加tzinfo?
最佳答案
我的理解是mongoengine不支持每个模型codec_options
。如果是这样,它们应该是opts
词典here的一部分。
但是,当Collection没有自己的集合时,PyMongo默认为数据库的codec_options
,您可以在向数据库发出任何请求之前,通过在应用程序中手动调用register_connection
进行设置。
在上面的示例中,您应像这样传递codec_options
:
with_timezone = CodecOptions()
connect(host="mongodb://localhost/datetimewithtz", codec_options=with_timezone)
关于python - 如何将CodecOptions应用于mongoengine集合以获取tzinfo?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37503932/