如果 UTC 始终可用,则使用不带时区的时间戳有任何缺点

Daj*_*aku 3 postgresql timestamp timezone

timestamp with time zone对比timestamp without time zone

我知道这timestamptz与在数据库中保存值时添加的时间戳无时区+(时区差)相同。也就是说,在数据库中,当存储时,它们都是无法区分的。

比如说,我决定只使用timestamp without time zone,即使是在推荐的情况下timestamp with time zone。我网站的用户可以记住,我和他们将始终使用 UTC 进行操作,即使我们碰巧处于不同的时区,效果会timestamp without time zone很好且没有缺陷吗?

Erw*_*ter 6

如果所有人都知道时间戳值应该代表 UTC 时间,那么基本上它应该可以工作。一个方便的优点是默认输入和输出噪音较小。

我还是会建议timestamptz。以下是一些原因:

1.

timestamptz从字面上看,它是 Postgres 中日期/时间类型中的“首选类型”。看:

test=> SELECT typname, typispreferred FROM pg_type WHERE typcategory = 'D';
   typname   | typispreferred 
-------------+----------------
 date        | f
 time        | f
 timestamp   | f
 timestamptz | t  -- !
 timetz      | f
 time_stamp  | f
(6 rows)
Run Code Online (Sandbox Code Playgroud)

该手册关于pg_types.

这有利于timestamptz类型/函数/运算符解析的极端情况。

2.

当您使用timestamptz文字作为数据输入时,它仅适用于 type timestamptz

'2020-04-22 04:46:46.790969+02'
Run Code Online (Sandbox Code Playgroud)

将其插入timestamp列中将忽略时间偏移(丢失信息)。必须timestamptz显式转换为 UTC 时间戳,然后使用以下内容转置为 UTC 时间戳:

'2020-04-22 04:46:46.790969+02'::timestamptz AT TIME ZONE 'UTC'
Run Code Online (Sandbox Code Playgroud)

相反的方向更不容易出错。timestamp将文字插入列中时timestamptz,在没有明确信息的情况下假定当前时区。

3.

now()transaction_timestamp()返回timestamptz。如果你需要timestamp,你必须施展。在内部,LOCALTIMESTAMP就是这样做的:它投射transaction_timestamp(). 要获取 UTC 的当前时间戳,您需要now() AT TIME ZONE 'UTC'或类似的。

4.

显示给定时区的时间戳更简单,基于timestamptz

SELECT my_timestamptz AT TIME ZONE 'US/Hawaii';
Run Code Online (Sandbox Code Playgroud)

这需要更多的工作timestamp我们知道现在应该是 UTC 时间。但 Postgres 不会这样做,直到我们明确表示:

SELECT my_timestamp AT TIME ZONE 'UTC' AT TIME ZONE 'US/Hawaii'
Run Code Online (Sandbox Code Playgroud)

有关的: