PostgreSQL带有时区的SQLalchemy和时间戳,为什么隐身模式不同于正常?

时间:2019-02-01 13:06:09

标签: python postgresql datetime sqlalchemy timezone

我正在使用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

1 个答案:

答案 0 :(得分:1)

datetime.today()返回当前本地时间的timestamp without timezone info(返回值为时区 naive )。问题的根源在于,在SQL Alchemy的postgres适配器和postgres本身之间的某个地方,它必须猜测一个时区。您可能会想像,如果未明确提供时区,则计算机系统倾向于采用UTC,但是用于工具套件的精确逻辑可能很复杂且难以调试(而且取决于系统级计算机的本地时区设置)数据库中的设置,会话级别设置以及工具制造商的偏好设置)。您可以通过以下任一方式回避整个蠕虫病毒罐:

  1. 在UTC中存储没有时区的所有时间戳,然后适当地转换为所需的时间戳

  2. 始终使用带时区的时间戳(例如,将datetime.today()替换为datetime.now(),并传递所需的时区,以便您始终处理时区 aware 值),因此计算机无需采用时区。

请注意,在postgres中,timestamp with time zone类型始终始终存储为UTC,没有任何额外的信息,数据库仅使用会话级配置来决定在输出时显示该时区。