Dan*_*ite 2 postgresql timezone datetime timestamp-with-timezone
I\xe2\x80\x99 已被调整为将过去的日期作为 UTC 存储在数据库中,因为这实际上是事件发生的时间。对于未来的日期,我会将其与特定时区一起存储,以避免诸如闰秒或时区规则更改之类的更改。
\n\nPostgres 有timestamp with timezone,但在幕后,它将其存储为 UTC,从而推断指定的时区是 UTC 的偏移量。如果时区规则发生更改,则不会反映在该列中。
在这种情况下有什么建议?
\n\n\n\n把它想象成一个日历事件。UTC 对此没有意义
\n
听起来您想存储相对于特定时区的本地时间timestamp。\n在这种情况下,请将 a (不带时区)和存储timezone在单独的列中。
例如,假设您想要记录 2030 年 2 月 26 日上午 10 点在芝加哥发生的事件,并且该事件必须在当地时间上午 10 点,无论该日期生效的时区规则如何。
\n\n如果数据库存储没有时区的时间戳:
\n\nunutbu=# 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+---------------------+-----------------+\nRun Code Online (Sandbox Code Playgroud)\n\n然后,您可以使用以下命令找到事件的 UTC 日期时间
\n\nunutbu=# 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+---------------------+\nRun Code Online (Sandbox Code Playgroud)\n\n该查询返回 UTC 日期时间 ,2030-02-26 16:00:00它对应于2030-02-26 10:00:00芝加哥的当地时间。
使用AT TIME ZONE 将时区规则的应用延迟到进行查询时而不是timestamptz插入查询时。
使用AT TIME ZONEon atimestamp将日期时间本地化为给定时区,但报告用户时区中的日期时间。\nAT TIME ZONE使用 on atimestamptz将日期时间转换为给定时区,然后删除偏移量,从而返回timestamp。\n上面AT TIME ZONE使用了两次:首先本地化 a timestamp,然后将返回的值转换timestamptz为新的时区 (UTC)。结果是timestampUTC 格式的。
下面是一个示例,演示了AT TIME ZONE\ 在timestamps 上的行为:
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+------------------------+\nRun Code Online (Sandbox Code Playgroud)\n\n2030-02-26 10:00:00-06和2030-02-26 08:00:00-08是相同的日期时间,但在不同的用户时区中报告。这显示芝加哥上午 10 点是洛杉矶上午 8 点(使用当前时区定义):
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+---------------------+\nRun Code Online (Sandbox Code Playgroud)\n\n使用AT TIME ZONE两次的替代方法是将用户时区设置为UTC。然后你可以使用
select localtime AT TIME ZONE tzone\nRun Code Online (Sandbox Code Playgroud)\n\n请注意,以这种方式完成时,timestamptz将返回 a 而不是 a timestamp。
请注意,存储本地时间可能会出现问题,因为可能存在不存在的时间和不明确的时间。\n例如,2018-03-11 02:30:00是 中不存在的本地时间America/Chicago。Postgresql 通过假设夏令时 (DST) 开始后的相应时间来标准化不存在的本地时间(就好像有人忘记将时钟向前设置一样):
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)\nRun Code Online (Sandbox Code Playgroud)\n\n不明确当地时间的一个例子2018-11-04 01:00:00是America/Chicago。由于夏令时,这种情况会发生两次。Postgresql 通过选择 DST 结束后的较晚时间来解决这种歧义:
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+---------------------+\nRun Code Online (Sandbox Code Playgroud)\n\n请注意,这意味着无法通过2018-11-04 06:00:00 UTC在时区中存储当地时间来引用America/Chicago:
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+---------------------+\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
1575 次 |
| 最近记录: |