【问题标题】:PostgreSQL SQLalchemy and timestamp with time zone, why is incognito different from normal?PostgreSQL SQLalchemy和带时区的时间戳,为什么隐身与正常不同?
【发布时间】:2019-06-26 01:41:20
【问题描述】:

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

这真的让我很担心。这是完全错误的。即使我将日期时间对象转换为本地时间。两个条目是同时做的,结果却不一样,这怎么可能?

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

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

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

编辑

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

编辑

我用SHOW timezone; 仔细检查了所有有问题的表,它们都正确返回Europe/Berlin

【问题讨论】:

  • 我假设Incognito,您指的是Chrome 浏览器Incognito window?对吗?
  • 您的查询中的会话时区设置可能不一致。我怀疑隐身窗口与它有什么关系。
  • 你有没有在postgresql.conf中设置过timezone =的值,如果有,是怎么设置的?
  • 是的,我指的是 chrome 隐身窗口。 @克里斯拉尔森

标签: python postgresql datetime sqlalchemy timezone


【解决方案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,没有额外信息,数据库只是使用会话级别的配置来决定在输出时将其显示为哪个时区。

【讨论】:

  • 很好的解释。这可能真的是问题所在。我明天测试一下。
  • 我将所有datetime.today() 替换为datetime.now(pytz.timezone('Europe/Berlin'))。现在它总是显示相同的时间,但它也在 postgres 中显示 +1 偏移量。我假设它告诉这个偏移量已经应用了。例如,如果我在当地时间 15:30 创建一个条目,它将显示在 DB 15:30 +1 偏移量中,这实际上是 UTC 14:30。所以我认为这意味着 14:30 已经应用了偏移量。
  • 这是正确的——Postgres 以显示时间和偏移量的格式显示带有 tz 值的时间戳。它以 UTC 格式将时间戳存储在数据库中,并将显示它调整为您配置的时区,显示应用的偏移量。
  • 感谢您的确认。
猜你喜欢
  • 2015-03-03
  • 1970-01-01
  • 1970-01-01
  • 2013-07-16
  • 2019-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-04
相关资源
最近更新 更多