PostgreSQL SQLalchemy 和 timestamp with time zone,为什么隐身模式和普通模式不同?
PostgreSQL SQLalchemy 和 timestamp with time zone,为什么隐身模式和普通模式不同?
我正在使用flask sqlalchemy和postgreSQL,并且在显示日期时间方面遇到了问题,调查此问题时,我发现了另一个奇怪的事情:\n在隐身模式下(Chrome浏览器标签)创建数据库条目会给出不同/错误的时间。\n编辑:这与隐身模式无关,两种情况都会在正常模式下发生。我还没有找出原因。\n这是代码:\n我更改了数据库的默认时区:\n
ALTER DATABASE postgres SET timezone TO 'Europe/Berlin';
\n模型:\n
class User(UserMixin, Base): __tablename__ = 'users' date_added = Column(DateTime(timezone=True), nullable=False)
\n我用于将日期时间添加到数据库的方法:\n
date_added=datetime.today()
\n在数据库中的显示效果(此时我的本地时间是13:53:46):\n在非隐身模式下创建条目:\n
timestamp with time zone 2019-02-01 13:53:46.73817+01
\n在隐身模式下创建条目:\n
timestamp with time zone 2019-02-01 12:53:46.73817+01
\n这真的让我担心。它简直是错误的。即使我将日期时间对象转换为本地时间。这两个条目是在同一时间完成的,但显示的结果不同,这怎么可能?\n另外,在HTML中查看这些日期时,postgreSQL不应用偏移量,所以第一个日期看起来是正确的,但第二个是错误的。\n最初,我只想找到一种方法,将所有日期时间对象存储在Europe/Berlin,并以Europe/Berlin时间返回它们,这样我就不必将UTC转换为Europe/Berlin,但现在我认为出了严重的问题。\n我已经仔细检查了我的代码,没有使用其他方法来操作日期时间对象。\n编辑:\n每次用户登录时,我都会保存一个日期时间。目前我在非隐身模式下尝试了这个。我的本地时间是14:13:33,但它保存到数据库中的时间却是:\n
2019-02-01 13:13:33.804339+01
\n这怎么可能?我知道它不可能是随机的,但现在看起来它似乎是随机保存有时带有UTC偏移量,有时带有Europe/Berlin偏移量。\n编辑:\n我使用`SHOW timezone;`仔细检查了所有相关的表,它们都正确返回`Europe/Berlin`。
PostgreSQL SQLalchemy和timestamp with time zone,为什么incognito和normal不同?
问题的出现原因是:在SQLalchemy的postgres适配器和postgres本身之间,需要猜测时区。如果没有明确提供时区,计算机系统往往倾向于假设为UTC,但是工具套件设置的精确逻辑可能很复杂且难以调试(可能取决于计算机上的本地时区设置、数据库中的系统级设置、会话级设置和工具制造商的偏好)。为了避免这个问题,可以采取以下解决方法:
1. 将所有的时间戳存储为不带时区的UTC时间,然后根据需要进行转换为所需的时间戳。
2. 始终使用带时区的时间戳(例如,用datetime.now()替换datetime.today(),并传入所需的时区),以便始终处理带有时区信息的值,这样计算机就不需要假设时区。
需要注意的是,在postgres中,timestamp with time zone类型始终以UTC存储,并且没有额外的信息。当输出时,数据库使用会话级配置来决定以哪个时区显示它。
非常好的解释。这可能真的是问题所在。我明天会进行测试。
我将所有的datetime.today()替换为datetime.now(pytz.timezone('Europe/Berlin'))。现在它总是显示相同的时间,但在postgres中也显示了+1的偏移量。我认为它表示这个偏移量已经被应用。例如,如果我在当地时间15:30创建一个条目,它将在数据库中显示为15:30 +1的偏移量,实际上是UTC 14:30。所以我认为它表示已经应用了14:30的偏移量。
这是正确的-- Postgres以显示时间和所显示时区的偏移量的格式显示带时区的时间戳值。它在数据库中以UTC存储时间戳,并在显示时根据您配置的时区进行调整,显示已应用的偏移量。
感谢您的确认。