【问题标题】:PostgreSQL timestamp with timezone apply offset when reading读取时带有时区的 PostgreSQL 时间戳应用偏移量
【发布时间】:2019-06-25 21:26:25
【问题描述】:

首先我知道有很多关于这个的线程,我可以使用那里的解决方案,f.e.编写一个 python 函数,将 datetime 对象转换为我需要的时区,并将其作为过滤器添加到 jinja2。

但我想跳过这一步。

通常 PostgreSQL 将日期时间对象保存在 UTC 中。

我所做的是:我将 postgreSQL 用于保存日期时间对象的默认时区更改为:Europe/Berlin

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

这行得通,SHOW timezone; 告诉我它的Europe/Berlin

但是 Postgres 的作用是,它仍然将日期时间保存为 UTC,但欧洲/柏林的偏移量为 +1,这实际上不是问题。

我假设在读取 datetime 对象时,Postgres 会应用偏移量并返回欧洲/柏林时间,但事实并非如此。它仍然返回 UTC 时间,那么更改时区有什么意义呢?

这个过滤器还是需要自己写,手动转换一下。

我认为应该有一种简单的方法在数据库级别应用偏移量,还是我错了?

编辑

一些可能对模型有所帮助的信息:

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

它在数据库中的样子:

这是我如何在 jinja2/html 中加载它的示例:

{{ tenant.date_added.strftime('%d.%m.%Y um %H:%M Uhr') }}

【问题讨论】:

    标签: postgresql timestamp-with-timezone


    【解决方案1】:

    首先,您可以在数据库中完全处理这个问题。处理时区时,要么始终使用timestamp with time zone,让数据库处理转换等,始终使用timestamp without time zone,存储UTC时间戳并让应用程序处理与时区处理。将这两者混合通常不是一个好主意。

    PostgreSQL 在内部存储 timestamp with time zone 作为 UTC 时间戳。转换为 string 时,例如当数据发送到客户端时,将数据转换为会话时区,该时区由timezone参数配置。

    timezone 设置为ALTER DATABASE 将更改所有未来会话的设置,也就是说,您必须断开连接并重新连接才能使新设置生效。

    但是,每个会话都可以免费(并鼓励)使用SET 命令或set_config 函数更改timezone,这决定了时间戳将转换到哪个时区。使用SHOW timezone 查看您当前的设置。

    如果您存储的时间戳没有明确的时区(如2019-02-01 12:00:00),它将在您当前的会话时区中进行解释。因此,如果那是Europe/Berlin,则内部存储的 UTC 时间戳将为2019-02-01 11:00:00 UTC。现在如果你SELECT 的值,它将显示为2019-02-01 12:00:00+01,因为那是你当前的时区偏移量。如果更改timezone,相同的值会以不同的方式显示。

    【讨论】:

    • 我有带时区的时间戳,数据库时区是 Europe/Berlin,所以它应该默认返回 Europe/Berlin。我将尝试重新启动数据库。感谢您的回复。
    • 现在是个问题。我使用 heroku postgres 并且无法重新启动数据库。还有其他方法吗?
    • 没有“数据库时区”之类的东西。只有一个会话时区。您不必重新启动数据库,只需断开并重新连接即可。
    • 这里发生了超级奇怪的事情。它显示了正确的时间。我以隐身模式打开网站,它再次显示 UTC 时间,切换回非隐身模式(时间是欧洲)它又是 UTC。
    • 你的解释是正确的。我认为问题出在其他地方。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-11
    • 2013-03-27
    • 2014-01-24
    • 2021-07-17
    相关资源
    最近更新 更多