在 postgres 中显式保留时区

rsm*_*idt 5 postgresql timestamp timezone

我一直在研究“查看”时间的不同方式以及如何在 Postgres 中正确映射它,但我仍然不确定实际使用什么。有几篇文章建议或者更确切地说说服您将日期存储为timestamp with time zone,而不是存储为 just timestamp。我尤其在夏令时方面遇到困难。

我的用例是一个简单的面向最终用户的应用程序,只能由“欧洲/柏林”时区的人员访问。用户撰写的帖子会与创建和更新的时间戳一起存储。

假设用户在 上发布了帖子2020-01-01T10:00:00+01。如果用户现在在同一天阅读该帖子,它应该显示posted on 1st of January at 10 am。如果同一篇文章7 月在柏林被点击,它仍然应该显示posted on 1st of January at 10 am“无论夏令时如何”。

我的直觉是将时间存储为 a timestamp without time zone,否则 Postgres 会将该时间转换为 UTC 并以这种方式存储。稍后我将无法参考该帖子发布的实际时区。在这种情况下,它会显示为posted on 1st of January at 11 am(由于柏林现在提前两个小时),如果作者要检查最初的时间,这可能会让他们感到困惑发表了这篇文章。

我的想法是否正确,我是否发现了不使用的极端情况之一timestamp with time zone,或者我在这里错过了一些重要的东西?

Erw*_*ter 3

\n

我的用例是一个简单的面向最终用户的应用程序,仅由“欧洲/柏林”时区的人员访问。[...]

\n

我的直觉现在是将时间存储为timestamp without time zone因为 [...]

\n

后来我将无法参考该帖子发布的实际时区。

\n
\n

这表明由于不幸的数据类型名称而产生的误解

\n
    \n
  • timestamp without time zone(= timestamp)
  • \n
  • timestamp with time zone( = timestamptz)
  • \n
\n

这两种数据类型都不存储任何时区信息。timestamptz只需添加输入和输出逻辑以考虑当前会话的timezone设置,并相应地从/到 UTC 时间进行投影。

\n

如果这让您感到困惑,请不要太尴尬,这已经发生在我们最好的人身上:

\n\n

在你的具体情况下

\n

如果你的说法可靠:

\n
\n

仅由“欧洲/柏林”时区的人员访问。

\n
\n

...那么你不妨只使用timestamp. 您知道相应的时区。并且输入和输出之间没有转换。timestamptz您可以通过以下方式即时转换:

\n
my_column AT TIME ZONE \'Europe/Berlin\'\n
Run Code Online (Sandbox Code Playgroud)\n

如果您的应用程序超出其当前范围,并且您需要切换到timestamptz轻松促进来自多个时区的输入,请使用以下命令进行转换:

\n
ALTER TABLE tbl ALTER col TYPE timestamptz\n   USING my_column AT TIME ZONE \'Europe/Berlin\'\n
Run Code Online (Sandbox Code Playgroud)\n

请务必使用时区名称“Europe/Berlin”,而不是无法根据 DST 变化进行调整的硬编码偏移量,也不要使用时区缩写,后者只是硬编码偏移量的名称 - 另一个那些非常常见的误解。

\n

或者timestmaptz立即使用以应对所有可能发生的情况。

\n

无论哪种方式,为了保留您所要求的时区,您需要显式存储它们(在附加列中),因为否则不会保存 - 并且您不能再假设“欧洲/柏林”。

\n

有关的:

\n\n