我正在使用flask sqlalchemy和postgreSQL,但显示的日期时间有问题,在调查此问题时,我发现了另外一件奇怪的事情:
以隐身模式创建数据库条目(chrome浏览器选项卡)会产生不同/错误的时间。 编辑:与隐身模式无关,两种情况都在正常模式下发生。我还没弄清楚为什么。
这是代码:
我更改了数据库的默认时区:
ALTER DATABASE postgres SET timezone TO 'Europe/Berlin';
模型:
class User(UserMixin, Base):
__tablename__ = 'users'
date_added = Column(DateTime(timezone=True), nullable=False)
我用于将日期时间添加到数据库的方法:
date_added=datetime.today()
它在数据库中的外观(我现在的本地时间是13:53:46):
创建不隐身的条目
timestamp with time zone
2019-02-01 13:53:46.73817+01
以隐身方式创建条目
timestamp with time zone
2019-02-01 12:53:46.73817+01
这真的让我担心。这是完全错误的。即使我将datetime对象转换为localtime。这两个条目是同时完成的,但是显示不同的结果,这怎么可能?
另外,在HTML中查看这些日期时,postgreSQL不会应用偏移量,因此第一个日期看起来正确,但是第二个错误。
最初,我只是想找到一种在欧洲/柏林存储所有日期时间对象并在欧洲/柏林时间返回它们的方法,因此我不必将UTC转换为欧洲/柏林,但是现在我认为出了点大问题。
我也到处都仔细检查过我的代码,我没有使用其他方法来操纵日期时间对象。
编辑
每次用户登录时,我都会保存一个日期时间。目前,我在不隐身的情况下尝试了此操作。我的本地时间是14:13:33
,但已保存到数据库中:
2019-02-01 13:13:33.804339+01
。这怎么可能?我知道它不能是随机的,但现在看来它的保存时间是随机的,有时UTC带有偏移,有时是Europe / Berlin带有偏移。
编辑
我用SHOW timezone;
仔细检查了所有有问题的表,它们都正确返回了Europe/Berlin
答案 0 :(得分:1)
datetime.today()
返回当前本地时间的timestamp without timezone info(返回值为时区 naive )。问题的根源在于,在SQL Alchemy的postgres适配器和postgres本身之间的某个地方,它必须猜测一个时区。您可能会想像,如果未明确提供时区,则计算机系统倾向于采用UTC,但是用于工具套件的精确逻辑可能很复杂且难以调试(而且取决于系统级计算机的本地时区设置)数据库中的设置,会话级别设置以及工具制造商的偏好设置)。您可以通过以下任一方式回避整个蠕虫病毒罐:
在UTC中存储没有时区的所有时间戳,然后适当地转换为所需的时间戳
始终使用带时区的时间戳(例如,将datetime.today()
替换为datetime.now()
,并传递所需的时区,以便您始终处理时区 aware 值),因此计算机无需采用时区。
请注意,在postgres中,timestamp with time zone
类型始终始终存储为UTC,没有任何额外的信息,数据库仅使用会话级配置来决定在输出时显示该时区。