【问题标题】:How do I apply CodecOptions to a mongoengine collection to get tzinfo?如何将 CodecOptions 应用于 mongoengine 集合以获取 tzinfo?
【发布时间】:2023-03-30 18:14:02
【问题描述】:

使用 mongoengine Document,当我从 mongo 加载 DateTimeField 时,它缺少 tzinfo。我们的策略应用程序希望所有日期时间都具有tzinfo

当我保存到 mongo 时,我知道 pymongo 对时区做了正确且可预测的事情;如果是 naive,则存储为 UTC 时间,如果有时区,则将其转换为 UTC,然后存储为 UTC 时间。到目前为止一切顺利。

不过,当我加载时,DateTimeField 总是给我一个天真的datetime。我知道这个datetime 是UTC,所以如果我愿意,我可以添加tzinfo,但我必须在我的应用程序的几十个地方这样做,这是对未来时区错误的保证,除非我使用自定义字段类型(参见下面的示例)。

引用:https://api.mongodb.com/python/current/examples/datetimes.html 我知道 pymongo 支持将 tzinfo 放在从数据库到达的对象上。我也知道我可以自己做到这一点,如下面的最小示例所示。 DateTimeTZFieldto_python 中添加tzinfo

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

【问题讨论】:

    标签: python mongodb pymongo mongoengine bson


    【解决方案1】:

    怎么样

    connect(...,  tz_aware=True,...)
    

    参数会被转发到MongoClient(..., tz_aware=True, ...)

    【讨论】:

      【解决方案2】:

      我的理解是 mongoengine 不支持 per-model codec_options。如果是这样,它们应该是 opts 字典 here 的一部分。

      但是,当 Collection 没有任何自己的集合时,PyMongo 默认使用数据库的 codec_options,您可以在向数据库发出任何请求之前,通过在应用程序中手动调用 register_connection 来设置这些。

      在上面的示例中,您应该像这样传递codec_options

      with_timezone = CodecOptions()
      connect(host="mongodb://localhost/datetimewithtz", codec_options=with_timezone)
      

      【讨论】:

      • 感谢您的周到回答,一旦我尝试过,我会回来的。我将实例化 CodecOptions(tz_aware=True),如果不对请告诉我。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-03
      • 1970-01-01
      • 1970-01-01
      • 2018-02-27
      • 2021-08-04
      • 1970-01-01
      相关资源
      最近更新 更多