在PostgreSQL中表示未来时间
我已经习惯于将过去的日期作为UTC存储在数据库中,因为事实上这是事件发生的时间。对于将来的日期,我会将其存储在特定的时区中,以避免诸如闰秒或时区规则更改之类的更改 Postgres具有带时区的时间戳,但在封面下,它将其存储为UTC,从而推断指定的时区是UTC的偏移量。如果时区规则要更改,则该列中不会反映这一点 在这种情况下,建议使用什么?特别是如果您想保护自己不受未来时间zune更改的影响,您应该使用带有时区的在PostgreSQL中表示未来时间,postgresql,datetime,timezone,timestamp-with-timezone,Postgresql,Datetime,Timezone,Timestamp With Timezone,我已经习惯于将过去的日期作为UTC存储在数据库中,因为事实上这是事件发生的时间。对于将来的日期,我会将其存储在特定的时区中,以避免诸如闰秒或时区规则更改之类的更改 Postgres具有带时区的时间戳,但在封面下,它将其存储为UTC,从而推断指定的时区是UTC的偏移量。如果时区规则要更改,则该列中不会反映这一点 在这种情况下,建议使用什么?特别是如果您想保护自己不受未来时间zune更改的影响,您应该使用带有时区的时间戳 PostgreSQL在内部存储自2000-01-01 00:00:00以来的微
时间戳
PostgreSQL在内部存储自2000-01-01 00:00:00以来的微秒数,这是不受时区更改影响的。如果您不断更新PostgreSQL,它将始终正确显示会话时区的绝对值
PostgreSQL中没有闰秒的规定
对于将来的日期,我会将其存储在特定的时区中,以避免诸如闰秒或时区规则更改之类的更改
这似乎落后了。与其他时区相比,UTC的主要优势在于它不太容易发生意外的未来变化:UTC仅在日历年的已知有限点引入闰秒;而且没有频繁的政治授权的抵消变化
将值存储在某些本地管理的时区中会使这些值(与UTC相比)更容易在未来发生任意、不可预测的含义变化
因此,一般建议是:将所有时间值(无论是日期还是日期+时间)作为UTC存储在数据库中,并在内部作为UTC值进行处理;并仅在外部接口上与本地时区进行转换
对于PostgreSQL,这意味着更喜欢带有时区的时间戳
把它想象成一个日历事件。UTC对此毫无意义
听起来您想要存储一个关于某个时区的localtime。
在这种情况下,将时间戳
(无时区)和时区
存储在单独的列中
例如,假设您想要记录2030年2月26日上午10点在芝加哥发生的事件
而且它必须在当地时间上午10点,而不考虑该日期生效的时区规则
如果数据库存储的时间戳没有时区:
unutbu=# select '2030-02-26 10:00:00'::timestamp as localtime, 'America/Chicago' AS tzone;
+---------------------+-----------------+
| localtime | tzone |
+---------------------+-----------------+
| 2030-02-26 10:00:00 | America/Chicago |
+---------------------+-----------------+
unutbu=# select '2018-11-04 00:59:59'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
| timezone |
+---------------------+
| 2018-11-04 05:59:59 |
+---------------------+
然后,您可以使用
unutbu=# select '2030-02-26 10:00:00'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
| timezone |
+---------------------+
| 2030-02-26 16:00:00 |
+---------------------+
查询返回UTC日期时间,2030-02-26 16:00:00
,它对应于芝加哥的2030-02-26 10:00:00
localtime
在时区使用
会将时区规则的应用延迟到进行查询时,而不是插入时间戳时
在时间戳上使用在时区
将日期时间定位到给定时区,但报告用户时区中的日期时间。
在时间戳
上使用在时区
将日期时间转换为给定的时区,然后删除偏移量,从而返回时间戳
。
上面,在时区
使用了两次:首先是本地化时间戳
,然后将返回的时间戳转换为新的时区(UTC)。结果是UTC中的时间戳
下面是一个示例,演示了时区的在时间戳
上的行为:
unutbu=# SET timezone = 'America/Chicago';
unutbu=# SELECT '2030-02-26 10:00:00'::timestamp AT TIME ZONE 'America/Chicago';
+------------------------+
| timezone |
+------------------------+
| 2030-02-26 10:00:00-06 |
+------------------------+
unutbu=# SET timezone = 'America/Los_Angeles';
unutbu=# SELECT '2030-02-26 10:00:00'::timestamp AT TIME ZONE 'America/Chicago';
+------------------------+
| timezone |
+------------------------+
| 2030-02-26 08:00:00-08 |
+------------------------+
2030-02-26 10:00:00-06
和2030-02-26 08:00:00-08
是相同的日期时间,但在不同的用户时区中报告。这表明芝加哥的上午10点是洛杉矶的上午8点(使用当前时区定义):
除了在时区两次使用之外,还有一种选择,那就是使用UTC
。那你可以用
select localtime AT TIME ZONE tzone
请注意,这样做时,将返回时间戳
,而不是时间戳
请注意,存储本地时间可能会有问题,因为可能存在不存在的时间和不明确的时间。
例如,2018-03-11 02:30:00
在America/Chicago
中是不存在的本地时间。Postgresql规范化不存在的本地时间,假定它是指夏时制(DST)开始后的相应时间(好像有人忘记将时钟向前拨):
本地时间不明确的一个例子是2018-11-04 01:00:00
中的America/Chicago
。由于DST,它发生两次。Postgresql通过在DST结束后选择更晚的时间来解决此歧义:
unutbu=# select '2018-11-04 01:00:00'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
| timezone |
+---------------------+
| 2018-11-04 07:00:00 |
+---------------------+
请注意,这意味着无法通过在America/Chicago
时区中存储本地时间来引用2018-11-04 06:00:00 UTC
:
unutbu=# select '2030-02-26 10:00:00'::timestamp as localtime, 'America/Chicago' AS tzone;
+---------------------+-----------------+
| localtime | tzone |
+---------------------+-----------------+
| 2030-02-26 10:00:00 | America/Chicago |
+---------------------+-----------------+
unutbu=# select '2018-11-04 00:59:59'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
| timezone |
+---------------------+
| 2018-11-04 05:59:59 |
+---------------------+
像日历事件一样思考。UTC对我们来说没有意义that@DanielA.White谢谢具体信息应修改问题描述,然后;您可以更新它以指定这些值的用途吗?