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