关于python:PostgreSQL SQLalchemy和带时区的时间戳,为什么隐姓埋名与正常情况不同?

PostgreSQL SQLalchemy and timestamp with time zone, why is incognito different from normal?

我正在使用flask sqlalchemy和postgreSQL,我对显示的日期时间有疑问,在调查这个问题时,我发现了另一个奇怪的事情:

在隐身模式下创建数据库条目(chrome浏览器选项卡)会给出不同/错误的时间。
编辑:它与隐身模式无关,两种情况都发生在正常模式下。我还没弄清楚原因。

这是代码:

我更改了数据库的默认时区:

1
ALTER DATABASE postgres SET timezone TO 'Europe/Berlin';

该模型:

1
2
3
class User(UserMixin, Base):
    __tablename__ = 'users'
    date_added = Column(DateTime(timezone=True), nullable=False)

我用来向DB添加日期时间的方法:

1
date_added=datetime.today()

它在数据库中的外观(我当时的当地时间是13:53:46):

创建不是隐身的条目

1
2
timestamp with time zone
2019-02-01 13:53:46.73817+01

以隐身方式创建条目

1
2
timestamp with time zone
2019-02-01 12:53:46.73817+01

这真让我担心。这完全是错的。即使我将datetime对象转换为localtime。两个条目都是同时完成的,但显示的结果不同,这怎么可能?

另外,当在HTML中查看这些日期时,postgreSQL不会应用偏移量,因此第一个日期看起来是正确的,但第二个日期是错误的。

最初我只是想找到一种方法在欧洲/柏林存储所有日期时间对象并在欧洲/柏林时间返回它们,所以我不必将UTC转换为欧洲/柏林,但现在我认为有些事情发生了可怕的错误。

我还在各处仔细检查了我的代码,我没有使用其他方法来操作datetime对象。

编辑

我每次用户登录时都会保存一个日期时间。目前我试着这个并非隐身。我的本地时间是14:13:33但它保存到数据库中:
2019-02-01 13:13:33.804339+01。这怎么可能呢?我知道它不能随意,但现在看起来它的随机存储时间有时候是带有偏移的UTC,有时欧洲/柏林有偏移。

编辑

我用SHOW timezone;仔细检查了所有相关表格,并且它们都正确返回Europe/Berlin


datetime.today()返回时间戳,没有当前本地时间的时区信息(返回的值是时区未定)。问题的根源在于SQL Alchemy的postgres适配器和postgres本身之间它必须在时区猜测。正如您可能想象的那样,如果没有明确提供时区,计算机系统倾向于采用UTC,但工具套件的精确逻辑可能很复杂且难以调试(我依赖于您计算机上的本地时区设置,系统级别)数据库中的设置,会话级别设置以及工具制造商的首选项)。你可以通过以下任何一种方式回避这整个蠕虫:

  • 以UTC为单位存储没有时区的所有时间戳,然后根据需要转换为所需的时间戳

  • 始终使用带时区的时间戳(即将datetime.today()替换为datetime.now()并传入所需的时区,以便始终处理时区感知值),??因此计算机不需要采用时区。

  • 请注意,在postgres中,timestamp with time zone类型仍然始终存储为UTC而没有额外信息,数据库只是使用会话级配置来决定在输出时将哪个时区显示出来。