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
-
我假设Incognito,您指的是Chrome浏览器Incognito window?那是对的吗?
-
可能会话时区设置在您的查询中不一致。我怀疑隐身窗口与它有什么关系。
-
可能重复:stackoverflow.com/questions/6663765/postgres-default-timezone?
-
您是否在postgresql.conf中设置了timezone =值,如果是这样,它是如何设置的?
-
是的我指的是镀铬隐身窗口。 @Chris Larson
-
我所做的就是写在问题中。要更改我仅使用的时区:ALTER DATABASE postgres SET timezone TO 'Europe/Berlin';我认为如果我对数据库级别有一般规则,则无需更改会话时区。
-
@MattJohnson我看到了这个帖子。这是我用alter database找到解决方案的地方。
-
查看PostgreSQL中有/无时区的时间戳之间的差异。 timestamp with time zone将日期时间以UTC NOT存储在本地时区。您的数据库时区设置只是告诉PostgreSQL在本地设置的时区而不是UTC中呈现时间戳的一种方法。但是,我不清楚您的问题的来源是基于您到目前为止发布的内容。
-
@benvc,我还是没有头绪。自动取款机。我休息了一下。下周将以新的头脑解决这个问题。谢谢你的链接
datetime.today()返回时间戳,没有当前本地时间的时区信息(返回的值是时区未定)。问题的根源在于SQL Alchemy的postgres适配器和postgres本身之间它必须在时区猜测。正如您可能想象的那样,如果没有明确提供时区,计算机系统倾向于采用UTC,但工具套件的精确逻辑可能很复杂且难以调试(我依赖于您计算机上的本地时区设置,系统级别)数据库中的设置,会话级别设置以及工具制造商的首选项)。你可以通过以下任何一种方式回避这整个蠕虫:
以UTC为单位存储没有时区的所有时间戳,然后根据需要转换为所需的时间戳
始终使用带时区的时间戳(即将datetime.today()替换为datetime.now()并传入所需的时区,以便始终处理时区感知值),??因此计算机不需要采用时区。
请注意,在postgres中,timestamp with time zone类型仍然始终存储为UTC而没有额外信息,数据库只是使用会话级配置来决定在输出时将哪个时区显示出来。
-
非常好的解释。 这可能是真正的问题。 我明天要测试一下。
-
我用datetime.now(pytz.timezone('Europe/Berlin'))替换了所有datetime.today()。 现在它总是显示相同的时间,但它也在postgres中显示+1偏移量。 我假设它告诉我已经应用了这个偏移量WAS。 例如,如果我在当地时间15:30创建一个条目,它将显示在DB 15:30 +1偏移量,实际上是UTC 14:30。 所以我认为这意味着14:30已经应用了偏移量。
-
这是正确的 - Postgres以显示时间和显示它的偏移量的格式显示tz值的时间戳。 它以UTC格式存储数据库中的时间戳,并将其显示为已调整为您配置的时区,显示应用的偏移量。
-
感谢您的确认。