将不带时区的时间戳转换为带时区的时间戳

Ale*_*hen 7 sql postgresql timestamp timestamp-with-timezone

我有一个类型为 nullable 的列timestamp without time zone。它以以下格式存储在我的 Postgres 数据库中:2021-06-24 11:00:00. 我想将其转换为可为空的timestamp with time zone类型,以便将其显示为2021-06-24 11:00:00.000-00. 请注意,没有时区转换。

该解决方案还应该允许从 转换timestamp with time zone为timestamp without time zone。我做了一些研究,但没有找到任何东西。

Erw*_*ter 8

假设一个表tbl具有时间戳列ts和表示 UTC 时间的时间戳,解决方案是:

ALTER TABLE tbl ALTER COLUMN ts type timestamptz USING ts AT TIME ZONE 'UTC';
Run Code Online (Sandbox Code Playgroud)

db<>在这里摆弄

您可能还必须调整列默认值。看:

误区一(问题)

我有一个类型为可空时间戳且没有时区的列。它以以下格式存储在我的 Postgres 数据库中:2021-06-24 11:00:00.

timestamp或timestamptz值永远不会以任何格式存储。格式化属于显示领域,并且很大程度上独立于存储类型。存储的是一个代表时间点的微秒分辨率的 8 字节整数。您显示的显示是使用 ISO 8601 的标准 Postgres 文本表示形式(输入也明确)。使用二进制协议的客户端可能会选择不同的表示形式。即使使用文本协议的客户端也可能选择以不同的方式重新格式化。

误解2(问题)

我想将其转换为可空值timestamp with time zone type ,以便将其显示为2021-06-24 11:00:00.000-00.

显示的时间偏移量与数据类型无关。-00仅当当前TimeZone设置(通常为 UTC)为真时,您才会看到附加时区。否则,您会得到不同的偏移量,并且时间戳也会相应地移动。

误区3(答案)

以UTC表示(这里的输出值看起来没有时区,但类型是timestamptz):

SELECT '2021-06-24 11:00:00'::timestamp AT TIME ZONE 'UTC' AT TIME
ZONE 'UTC';
=> 2021-06-24 11:00:00
Run Code Online (Sandbox Code Playgroud)

否,输出值的类型是timestamp。timestamptz在默认文本表示形式中,永远不会“看起来”像timestamp. timestamp从来没有“有”时区。甚至没有timestamptz“有”时区,它只是显示给定的时区。这两种类型都不存储任何时区信息。看:

误区四(答案)

要将 timestamptz 转换回 UTC 时间的时间戳:

SELECT ('2021-06-24 11:00:00-00'::timestamptz AT TIME ZONE 'UTC')::timestamp;
=> 2021-06-24 11:00:00
Run Code Online (Sandbox Code Playgroud)

不只是:

SELECT '2021-06-24 11:00:00-00'::timestamptz AT TIME ZONE 'UTC';
Run Code Online (Sandbox Code Playgroud)

结果是类型timestamp。没有额外的演员阵容。
该AT TIME ZONE构造timestamp在和之间进行转换timestamptz。结果类型始终从输入切换。

基础知识在这里:


Rob*_*bel 3

您正在寻找AT TIME ZONE,这有点令人困惑,但可以做您需要它做的一切。

要将已知的 UTC 时间戳转换为 timestamptz:

SELECT '2021-06-24 11:00:00'::timestamp AT TIME ZONE 'UTC';
=> 2021-06-24 06:00:00-05
Run Code Online (Sandbox Code Playgroud)

所有 timestamptz 值都以 UTC 内部存储在 Postgres 中,并且不保留它们插入的时区,因此它们将显示在您的连接时区中。您可以通过再次使用将 timestamptz 转换回所需区域中的时间戳AT TIME ZONE(正如 Erwin 下面指出的,AT TIME ZONE始终在 timestamp 和 timestamptz 之间切换):

SELECT '2021-06-24 11:00:00-00'::timestamptz AT TIME ZONE 'UTC';
=> 2021-06-24 11:00:00

SELECT '2021-06-24 11:00:00-00'::timestamptz AT TIME ZONE 'America/Chicago';
=> 2021-06-24 06:00:00
Run Code Online (Sandbox Code Playgroud)