代表 PostgreSQL 中的未来时间

Dan*_*ite 2 postgresql timezone datetime timestamp-with-timezone

I\xe2\x80\x99 已被调整为将过去的日期作为 UTC 存储在数据库中,因为这实际上是事件发生的时间。对于未来的日期,我会将其与特定时区一起存储,以避免诸如闰秒或时区规则更改之类的更改。

\n\n

Postgres 有timestamp with timezone,但在幕后,它将其存储为 UTC,从而推断指定的时区是 UTC 的偏移量。如果时区规则发生更改,则不会反映在该列中。

\n\n

在这种情况下有什么建议?

\n

unu*_*tbu 5

\n

把它想象成一个日历事件。UTC 对此没有意义

\n
\n\n

听起来您想存储相对于特定时区的本地时间timestamp。\n在这种情况下,请将 a (不带时区)和存储timezone在单独的列中。

\n\n

例如,假设您想要记录 2030 年 2 月 26 日上午 10 点在芝加哥发生的事件,并且该事件必须在当地时间上午 10 点,无论该日期生效的时区规则如何。

\n\n

如果数据库存储没有时区的时间戳:

\n\n
unutbu=# select \'2030-02-26 10:00:00\'::timestamp as localtime, \'America/Chicago\' AS tzone;\n+---------------------+-----------------+\n|      localtime      |      tzone      |\n+---------------------+-----------------+\n| 2030-02-26 10:00:00 | America/Chicago |\n+---------------------+-----------------+\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后,您可以使用以下命令找到事件的 UTC 日期时间

\n\n
unutbu=# select \'2030-02-26 10:00:00\'::timestamp AT TIME ZONE \'America/Chicago\' AT TIME ZONE \'UTC\';\n+---------------------+\n|      timezone       |\n+---------------------+\n| 2030-02-26 16:00:00 |\n+---------------------+\n
Run Code Online (Sandbox Code Playgroud)\n\n

该查询返回 UTC 日期时间 ,2030-02-26 16:00:00它对应于2030-02-26 10:00:00芝加哥的当地时间。

\n\n

使用AT TIME ZONE 将时区规则的应用延迟到进行查询时而不是timestamptz插入查询时。

\n\n
\n\n

使用AT TIME ZONEon atimestamp将日期时间本地化为给定时区,但报告用户时区中的日期时间。\nAT TIME ZONE使用 on atimestamptz将日期时间转换为给定时区,然后删除偏移量,从而返回timestamp。\n上面AT TIME ZONE使用了两次:首先本地化 a timestamp,然后将返回的值转换timestamptz为新的时区 (UTC)。结果是timestampUTC 格式的。

\n\n

下面是一个示例,演示了AT TIME ZONE\ 在timestamps 上的行为:

\n\n
unutbu=# SET timezone = \'America/Chicago\';\nunutbu=# SELECT \'2030-02-26 10:00:00\'::timestamp AT TIME ZONE \'America/Chicago\';\n+------------------------+\n|        timezone        |\n+------------------------+\n| 2030-02-26 10:00:00-06 |\n+------------------------+\n\nunutbu=# SET timezone = \'America/Los_Angeles\';\nunutbu=# SELECT \'2030-02-26 10:00:00\'::timestamp AT TIME ZONE \'America/Chicago\';\n+------------------------+\n|        timezone        |\n+------------------------+\n| 2030-02-26 08:00:00-08 |\n+------------------------+\n
Run Code Online (Sandbox Code Playgroud)\n\n

2030-02-26 10:00:00-062030-02-26 08:00:00-08是相同的日期时间,但在不同的用户时区中报告。这显示芝加哥上午 10 点是洛杉矶上午 8 点(使用当前时区定义):

\n\n
unutbu=# SELECT \'2030-02-26 10:00:00-06\'::timestamptz AT TIME ZONE \'America/Los_Angeles\';\n+---------------------+\n|      timezone       |\n+---------------------+\n| 2030-02-26 08:00:00 |\n+---------------------+\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

使用AT TIME ZONE两次的替代方法是将用户时区设置UTC。然后你可以使用

\n\n
select localtime AT TIME ZONE tzone\n
Run Code Online (Sandbox Code Playgroud)\n\n

请注意,以这种方式完成时,timestamptz将返回 a 而不是 a timestamp

\n\n
\n\n

请注意,存储本地时间可能会出现问题,因为可能存在不存在的时间和不明确的时间。\n例如,2018-03-11 02:30:00是 中不存在的本地时间America/Chicago。Postgresql 通过假设夏令时 (DST) 开始后的相应时间来标准化不存在的本地时间(就好像有人忘记将时钟向前设置一样):

\n\n
unutbu=# select \'2018-03-11 02:30:00\'::timestamp AT TIME ZONE \'America/Chicago\' AT TIME ZONE \'UTC\';\n+---------------------+\n|      timezone       |\n+---------------------+\n| 2018-03-11 08:30:00 |\n+---------------------+\n(1 row)\n\nunutbu=# select \'2018-03-11 03:30:00\'::timestamp AT TIME ZONE \'America/Chicago\' AT TIME ZONE \'UTC\';\n+---------------------+\n|      timezone       |\n+---------------------+\n| 2018-03-11 08:30:00 |\n+---------------------+\n(1 row)\n
Run Code Online (Sandbox Code Playgroud)\n\n

不明确当地时间的一个例子2018-11-04 01:00:00America/Chicago。由于夏令时,这种情况会发生两次。Postgresql 通过选择 DST 结束后的较晚时间来解决这种歧义:

\n\n
unutbu=# select \'2018-11-04 01:00:00\'::timestamp AT TIME ZONE \'America/Chicago\' AT TIME ZONE \'UTC\';\n+---------------------+\n|      timezone       |\n+---------------------+\n| 2018-11-04 07:00:00 |\n+---------------------+\n
Run Code Online (Sandbox Code Playgroud)\n\n

请注意,这意味着无法通过2018-11-04 06:00:00 UTC在时区中存储当地时间来引用America/Chicago

\n\n
unutbu=# select \'2018-11-04 00:59:59\'::timestamp AT TIME ZONE \'America/Chicago\' AT TIME ZONE \'UTC\';\n+---------------------+\n|      timezone       |\n+---------------------+\n| 2018-11-04 05:59:59 |\n+---------------------+\n
Run Code Online (Sandbox Code Playgroud)\n