后端代码统一使用时区感知datetime对象及数据库取值方案问询
可落地的替代方案如下
不需要每次手动追加replace(tzinfo=timezone.utc)的方案有多个,根据你的技术栈选适配的即可:
- 数据库字段类型调整
把存储时间的字段改为带时区的时间类型,比如PostgreSQL的TIMESTAMPTZ、MySQL的TIMESTAMP(注意MySQL的DATETIME类型不带时区,TIMESTAMP默认带时区),配置数据库全局时区为UTC后,查询返回的datetime对象默认就是带UTC时区的感知对象,无需额外转换。 - ORM层统一配置
如果你用SQLAlchemy之类的ORM框架,直接给时间字段的定义加上时区参数即可,示例配置:
配置后查询得到的from sqlalchemy import DateTime, Column from sqlalchemy.ext.declarative import declarative_base import datetime Base = declarative_base() class User(Base): __tablename__ = 'user' # 加timezone=True参数,ORM会自动处理时区转换,查询返回感知对象 expires_at = Column(DateTime(timezone=True), default=datetime.datetime.now(datetime.timezone.utc))user.expires_at直接就是带UTC时区的感知对象,可以直接和datetime.now(timezone.utc)比较。 - 模型层封装统一处理逻辑
如果不方便改数据库字段类型,可以在模型层加通用的属性封装,避免每次业务代码重复写转换逻辑,示例:
业务代码直接使用class User(Base): __tablename__ = 'user' expires_at = Column(DateTime) @property def expires_at_aware(self): return self.expires_at.replace(tzinfo=datetime.timezone.utc)if user.expires_at_aware < datetime.now(timezone.utc):即可。
不推荐把当前感知时间转为原生对象和数据库字段比较的写法,会破坏统一使用感知对象的规范,后续如果服务器时区调整很容易出隐性bug。
内容的提问来源于stack exchange,提问作者Paul Chuang
相关产品推荐
相关产品推荐

