简体   繁体   English

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

[英]Convert timestamp without timezone into timestamp with timezone

I have a column that is of type nullable timestamp without time zone .我有一个类型为 nullable timestamp without time zone It is stored in my Postgres database in this format: 2021-06-24 11:00:00 .它以这种格式存储在我的 Postgres 数据库中: 2021-06-24 11:00:00 And I would like to convert it to a nullable timestamp with time zone type such that it would be displayed as 2021-06-24 11:00:00.000-00 .我想将其转换为timestamp with time zone类型的可为空timestamp with time zone ,以便将其显示为2021-06-24 11:00:00.000-00 Notice that there is no timezone conversion.请注意,没有时区转换。

The solution should also allow to convert from timestamp with time zone to timestamp without time zone .该解决方案还应允许将timestamp with time zone转换为timestamp without time zone I did some research and was not able to find anything.我做了一些研究,但找不到任何东西。

You're looking for AT TIME ZONE , which is a little confusing but can do everything you need it to.您正在寻找AT TIME ZONE ,这有点令人困惑,但可以做您需要的一切。

To convert a timestamp known to be UTC to a timestamptz:要将已知为 UTC 的时间戳转换为时间戳:

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

All timestamptz values are stored internally in Postgres in UTC, and do not retain the timezone they were inserted at, so they will then show up in whatever your connection timezone is.所有 timestamptz 值都以 UTC 格式存储在 Postgres 内部,并且不保留它们插入的时区,因此它们将显示在您的连接时区中。 You can cast a timestamptz back to a timestamp in your desired zone by using AT TIME ZONE again (as Erwin pointed out below, AT TIME ZONE always switches between timestamp and timestamptz):您可以再次使用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

Assuming a table tbl with a timestamp column ts and timestamps that represent UTC time, the solution is:假设表tbl的时间戳列ts和时间戳表示 UTC 时间,解决方案是:

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

db<>fiddle here db<> 在这里摆弄

You may have to adapt the column default, too.您可能还需要调整列默认值。 See:看:

Misunderstanding 1 (question)误会1(问题)

I have a column that is of type nullable timestamp without time zone.我有一个没有时区的可为空时间戳类型的列。 It is stored in my Postgres database in this format: 2021-06-24 11:00:00 .它以这种格式存储在我的 Postgres 数据库中: 2021-06-24 11:00:00

timestamp or timestamptz values are never stored in any format. timestamptimestamptz值永远不会以任何格式存储。 Formatting is in the domain of display , and largely independent from the storage type.格式化属于display领域,并且在很大程度上独立于存储类型。 What's stored is an 8-byte integer quantity with microsecond resolution representing a point in time.存储的是一个 8 字节的整数,其分辨率为微秒,表示一个时间点。 The display you show is the standard Postgres text representation using ISO 8601 (also unambiguous for input).您显示的显示是使用 ISO 8601 的标准 Postgres 文本表示(对于输入也是明确的)。 Clients using the binary protocol might choose a different representation.使用二进制协议的客户端可能会选择不同的表示。 Even clients using the text protocol might choose to reformat differently.即使是使用文本协议的客户端也可能选择以不同方式重新格式化。

Misunderstanding 2 (question)误会2(问题)

I would like to convert it to a nullable timestamp with time zone type such that it would be displayed as 2021-06-24 11:00:00.000-00 .我想将其转换为timestamp with time zone type的可为空timestamp with time zone type ,以便将其显示为2021-06-24 11:00:00.000-00

The displayed time offset is not determined by the data type.显示的时间偏移不是由数据类型决定的。 You'll only see timezone -00 appended if that's true for the current TimeZone setting (typically UTC).如果当前时TimeZone设置(通常是 UTC)是这样,您只会看到附加时区-00 Else, you get a different offset, and the timestamp is shifted accordingly.否则,您会得到不同的偏移量,时间戳也会相应地移动。

Misunderstanding 3 (answer)误会3(答案)

To represent it in UTC (the output value here looks like it has no timezone, but the type is timestamptz):用UTC表示(这里的输出值看起来没有时区,但类型是timestamptz):

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

No, the type of the output value is timestamp .不,输出值的类型是timestamp timestamptz in default text representation never "looks" like timestamp .默认文本表示中的timestamptz永远不会“看起来”像timestamp timestamp never "has" a time zone. timestamp从不“具有”时区。 Not even timestamptz "has" a time zone, it's just displayed for a given time zone.甚至timestamptz都没有“有”时区,它只是针对给定的时区显示。 Neither of the two types stores any time zone information at all.这两种类型都不存储任何时区信息。 See:看:

Misunderstanding 4 (answer)误会4(答案)

To cast a timestamptz back to a timestamp at UTC time:要将时间戳转换回 UTC 时间的时间戳:

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

No. Just:不只是:

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

The result is type timestamp .结果是类型timestamp No additional cast.没有额外的演员。
The AT TIME ZONE construct converts between timestamp and timestamptz . AT TIME ZONE构造timestamptimestamptz之间进行转换。 The resulting type is always switched from the input.结果类型总是从输入切换。

Basics here:这里的基础知识:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM