【问题标题】:Convert timestamp without timezone into timestamp with timezone将不带时区的时间戳转换为带时区的时间戳
【发布时间】:2021-09-22 21:20:24
【问题描述】:

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

【问题讨论】:

    标签: sql postgresql timestamp timestamp-with-timezone


    【解决方案1】:

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

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

    db小提琴here

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

    误解1(问题)

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

    timestamp or timestamptz 值永远不会以任何格式存储。格式化属于 display 领域,并且很大程度上独立于存储类型。存储的是一个 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
    

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

    误解 4(答案)

    将 timestamptz 转换回 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 之间转换。结果类型总是从输入切换。

    这里的基本信息:

    【讨论】:

    • 感谢欧文的更正。我经常使用AT TIME ZONE 将时间戳转换为时间戳,但我显然不了解它的完整用法,也没有进行研究。我已更新我的答案以删除不正确的信息。
    【解决方案2】:

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

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

    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 将 timestamptz 转换回所需区域中的时间戳(正如 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
    

    【讨论】:

    • 这会返回修改后的值,对吧?如果我想用转换后的新类型timestamp with time zone修改现有的timestamp without time zone怎么办?
    • @AlexChen - 你的意思是你想将你的列从时间戳转换为时间戳?如果是这样,dba.stackexchange.com/questions/134385/… 应该有你需要的信息。请注意,它还如何使用AT TIME ZONE 来确保转换过程中以正确的方式进行转换。
    • 存在一些误解。评论太多,我添加了答案。
    • 现在非常有用的答案!
    猜你喜欢
    • 2018-12-18
    • 1970-01-01
    • 2019-10-07
    • 2015-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-02
    • 1970-01-01
    相关资源
    最近更新 更多