【问题标题】:How do I insert a universally coordinated time into a PostgreSQL TIMESTAMP column?如何将通用协调时间插入 PostgreSQL TIMESTAMP 列?
【发布时间】:2017-11-15 17:04:20
【问题描述】:

我的数据库和客户端目前在 America/New_York,但可以移动到任何地方。

SHOW TIMEZONE; -- America/New_York

CREATE TABLE times (
  t TIMESTAMP WITHOUT TIME ZONE
);

INSERT INTO times VALUES
  (NOW()),
  (NOW() AT TIME ZONE 'UTC');

SELECT t FROM times;
-- 2017-06-13 14:53:17.766969
-- 2017-06-13 18:53:17.766969

这是出乎意料的。我认为我的 SELECT 将为两条记录返回相同的值。

当我将当前时间插入t 列时,我希望它表示任何时区的当前时间(数据库是否将基础值存储为当前时间 UTC)。这样,无论数据库在哪个时区运行,或者客户端在哪个时区运行,每个人都可以就通用协调的固定时间点达成一致。

插入记录以使世界上每个人都知道我引用的是“UTC”时间的正确方法是什么?

【问题讨论】:

  • 我不清楚你在问什么 - 如果你想要 UTC 值,为什么不直接使用 NOW() AT TIME ZONE 'UTC' 呢?然后记录它始终是UTC,你没事吧?
  • 如果我 SELECT t AT TIME ZONE 'UTC' FROM times; 返回: -- 2017-06-13 10:53:17.766969 -- 2017-06-13 14:53:17.766969 我不确定发生了什么存储层。但是 UTC 的 INSERT 和 UTC 的 SELECT 对我来说似乎不连贯。
  • suspect (给定您所说的值)SELECT t AT TIME ZONE 'UTC' 实际上是在说,“假设表中的值是 UTC,并将它们转换为本地时间。”
  • This:postgresql.org/docs/9.1/static/… 会有点同意这一点,如果生成的“带时区的时间戳”被隐式转换为系统本地区域......(我同意 SQL 数据库通常已经做了一个诚然,这真是一团糟。)
  • 啊,是的,这就是行为。我看到如何记录这一点:“始终使用 NOW() AT TIME ZONE 'UTC' 插入并选择不指定时区来检索 UTC 时间戳。”

标签: postgresql timestamp


【解决方案1】:

首先,SELECT 似乎假定没有时区字段的时间戳存储在本地时区中。试试SET TIME ZONE 'UTC+<n>SELECT 的输出不会改变(即,如果没有存储时区,时间戳就不会意味着 UTC!)

timestamp with time zoneSELECT 类型的字段正确地将输出转换为当前时区。

因此,当您说 AT TIME ZONE 'UTC' 时,您将时间转换为 UTC,然后丢弃时区,使 Postgres 认为您正在处理本地时间。

您可以通过添加另一个 AT TIME ZONE 'UTC' 子句来重新引入 UTC 时区:

# select pg_typeof(now() at time zone 'utc');
timestamp without time zone

# select pg_typeof(now() at time zone 'utc' at time zone 'utc'); 
timestamp with time zone

底线:如果您坚持在没有时区的情况下工作,我要么总是使用TIME WITH TIME ZONE,要么总是将数据库时区设置为UTC。两种类型的存储大小似乎相同(64 位)。

【讨论】:

    猜你喜欢
    • 2015-04-01
    • 2019-08-23
    • 2013-07-05
    • 2012-08-05
    • 2018-03-27
    • 1970-01-01
    • 1970-01-01
    • 2013-04-25
    • 2020-07-24
    相关资源
    最近更新 更多