我有一张这样的桌子。
create table public.test123
(id int not null primary key, dt timestamp null default clock_timestamp());
Run Code Online (Sandbox Code Playgroud)
然后,我从 2 个不同的客户端会话插入其中,第一个会话来自 PG Admin,第二个会话来自 DBeaver。
在我运行的第一个会话中,show timezone;它返回UTC.
所以本次会话的时区是UTC。因此,从本次会议开始,我做了如下插入。
insert into public.test123(id) values (1);
Run Code Online (Sandbox Code Playgroud)
在第二次会议中,我有时区America/New_York,我就这样做了。
insert into public.test123(id) values (2);
Run Code Online (Sandbox Code Playgroud)
我运行这两个插入的时间间隔只有几秒钟。
但我在数据库中得到两个非常不同的值,例如
id|dt |
--|-------------------|
1|2020-06-05 14:38:18|
2|2020-06-05 10:38:26|
Run Code Online (Sandbox Code Playgroud)
我一直认为在这种情况下clock_timestamp()调用是在服务器上执行的,客户端会话的时区应该不重要。我期望得到两个相隔几秒的值,而不是相隔 4 小时的值。
我缺少什么?
另外,有没有办法获得独立于客户端会话时区的时间戳?
如何创建一个具有默认时间戳值的列,该值真正独立于客户端会话的时区?
tl;dr:切换到时间戳。
timestamp我将通过它们的简称来引用这些类型: timestamp without time zoneistimestamp和timestamp with time zoneis timestamptz。
两者timestamp都timestamptz存储绝对时间点。timestamp with time zone还记录输入的时区。
例如,2020-06-05 20:22:48Z和2020-06-05 13:22:48-0700都代表同一时刻,但第一个采用通用协调时间,另一个采用 7 小时偏移(太平洋夏令时)。
timestamptz将存储2020-06-05 13:22:48-0700为2020-06-05 20:22:48,绝对时间点,但还要记住它是以 7 小时偏移量输入的。当您检索它时,您将得到2020-06-05 13:22:48-0700与 相同的时间2020-06-05 20:22:48Z。
timestamp将完全忽略时区。它存储2020-06-05 13:22:48-0700为2020-06-05 13:22:48,没有时区,没有转换,仅此而已。
针对具体问题:dt timestamp null default clock_timestamp()
clock_timestamp()返回timestamptz,但您将其存储在timestamp. Postgres 只需删除时区即可将其中一个转换为另一个。它不会转换它。如果时区是 UTC 并且它2020-06-05 20:22:48Z会存储2020-06-05 20:22:48. 如果时区位于美国/纽约并且它将2020-06-05 16:22:48-0400存储2020-06-05 16:22:48.
还有...有没有办法获得独立于客户端会话时区的时间戳?
它们都独立于客户端的时区,这是类型转换的问题。切换到timestamptz。
时区很复杂,但在将时间戳移入和移出数据库时,有两种处理时区的策略。
timestamp并始终以 UTC 时间工作。timestamptz并始终包含时区。前者比较简单,很多框架都采用这种方式。但我更喜欢后者,因为尽管它们很复杂且令人恼火,但人们喜欢与太阳隐约同步的时间。
| 归档时间: |
|
| 查看次数: |
5499 次 |
| 最近记录: |