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

时间:2021-07-13 20:18:36

标签: sql postgresql timestamp timestamp-with-timezone

我有一个类型为可空 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。我做了一些研究,但没有找到任何东西。

2 个答案:

答案 0 :(得分:2)

您正在寻找 AT TIME ZONE,这有点令人困惑,但可以满足您的所有需求。

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

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

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

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

答案 1 :(得分:1)

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

ALTER TABLE tbl ALTER COLUMN ts type timestamptz USING ts AT TIME ZONE 'UTC';

db<>fiddle here

您可能还需要调整列默认值。见:

误解 1(问题)

<块引用>

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

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

误解 2(问题)

<块引用>

我想将其转换为可为空的 timestamp with time zone type 这样它就会显示为 2021-06-24 11:00:00.000-00

显示的时间偏移不是由数据类型决定的。如果当前 TimeZone setting(通常是 UTC)是这样,您只会看到附加时区 -00。否则,您会得到不同的偏移量,时间戳也会相应地移动。

误解 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

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

误解 4(答案)

<块引用>

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

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

没有。只是:

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

结果是类型 timestamp。没有额外的演员。
AT TIME ZONE constructtimestamptimestamptz 之间转换。结果类型总是从输入切换。

此处的基础知识: