【问题标题】:UTC is different on 2 servers for same database同一数据库的 2 台服务器上的 UTC 不同
【发布时间】:2020-05-05 15:09:05
【问题描述】:

我有一台在 UTC 时间的服务器和一台在 EST 的服务器。现在我从 UTC 数据库中转储数据库并将其导入 EST 数据库。由于时间戳始终保存为 UTC,因此我找不到为同一查询获得两个不同结果的原因:

选择时区'UTC'的reported_on,按reported_on desc从数据顺序中选择温度;

UTC 服务器:

 temperature |                device                |          timezone          
-------------+--------------------------------------+----------------------------
        17.2 | ------------------------------------ | 2020-05-05 12:13:16.256+00

EST 服务器:

 temperature |                device                |          timezone          
-------------+--------------------------------------+----------------------------
        17.2 | ------------------------------------ | 2020-05-05 14:13:16.256+02

我在这里缺少什么?如何在没有时区的情况下查询数据,我需要 UTC 时间,而不是 +02 时间?我怎样才能做到这一点?

编辑: 我通过nodejs添加了这些行:

INSERT INTO data(device, reported_on, temperature, humidity) VALUES($1, to_timestamp(' + Date.now() /1000.0 + '), $2, $3) RETURNING *

列的类型是: 在 TIMESTAMP 上报告,

更新: 更改时区解决了这个问题!

ALTER DATABASE sensors SET timezone TO 'UTC';
SELECT pg_reload_conf();

【问题讨论】:

  • "由于时间戳总是保存为 UTC" - 您能告诉我们表格是如何定义的以及您是如何插入时间的吗?
  • 我已将信息添加到原始问题中。该行定义为时间戳

标签: postgresql


【解决方案1】:

这是关于您的本地数据库配置的。我在本地创建了一个虚拟数据库,结果是这样的:

test=# CREATE TABLE timestamptest (timezone TIMESTAMPTZ);`

显示了我的时区模式:

test=# SHOW TIMEZONE;
 TimeZone 
----------
 UTC
(1 row)

并在里面插入了一些值:

test=# SELECT * FROM timestamptest;
           timezone            
-------------------------------
 2020-05-05 15:26:27.377549+00
 2020-05-05 15:28:14.014597+00
(2 rows)

现在,我更改了本地时区变量:

test=# SET TIME ZONE 'America/Montreal';
SET

并再次选择信息:

test=# INSERT INTO timestamptest VALUES (now());
INSERT 0 1
test=# SELECT * FROM timestamptest ;
           timezone            
-------------------------------
 2020-05-05 11:26:27.377549-04
 2020-05-05 11:28:14.014597-04
(2 rows)

我的时区不同,因为SET 命令:

test=# SHOW timezone;
     TimeZone     
------------------
 America/Montreal
(1 row)

您可以更改您的本地配置,并且关于您在问题中显示的选择,导入似乎是正确的,只是需要设置本地时间戳配置等于另一个。

请注意,时间戳末尾的-04 表明您的时间与最初的-00 相比变化了4 小时。只是一个格式输出。

更多信息在这里:here on postgresql docs

【讨论】:

    【解决方案2】:

    “时间戳始终保存为 UTC”的说法不正确。不带时间的时间戳(timestamp)与本地时间一起存储,带时区的时间戳(timestamptz)始终以UTC存储。来自documentation

    timestamp 没有时区,PostgreSQL 会默默忽略任何时间 区域指示。也就是说,结果值是从 输入值中的日期/时间字段,并且未针对时间进行调整 区域。

    对于带时区的时间戳,内部存储的值始终在 UTC(通用协调时间,传统上称为格林威治标准时间) 时间,格林威治标准时间)。指定了明确时区的输入值是 使用该时区的适当偏移量转换为 UTC。如果 输入字符串中没有说明时区,则假定为 在系统的 TimeZone 参数指示的时区,并且是 使用时区的偏移量转换为 UTC。

    使用“EST”或任何其他时区缩写时要非常小心,而应使用full timezone name。缩写表示固定的 UTC 偏移量(即 EST 始终为 UTC-5,EDT 始终为 UTC-4)并且不识别夏令时 (DST)。另一方面,全名(即 US/Central' 或 'America/Montreal' 或任何其他完整时区名称)是 DST 感知的,并相应地调整 UTC 偏移量。

    与 pg_timezone_abbrevs 中显示的缩写不同,其中许多 名称暗示了一组夏令时转换日期规则。

    您可以通过以下方式观察:

    select * from pg_timezone_abbrevs where abbrev in ('EDT', 'EST')
    select * from pg_timezone_names  where name in ('US/Eastern','America/New_York','America/Montreal')
    

    【讨论】:

      【解决方案3】:

      列的类型是TIMESTAMP*"

      我猜是你的问题。 You'll want 改为使用 TIMESTAMP WITH TIME ZONE。或者,不要在 SELECT 语句中使用 AT TIME ZONE 'UTC',这样无论时区如何,您都可以返回存储的相同时间戳。

      SELECT reported_on AT TIME ZONE 'UTC' 中发生的事情是存储的日期从数据库的本地时区转换为 UTC。在具有不同本地时区的第二个数据库中,这是不同的转换,导致结果中的偏移量。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-17
        • 1970-01-01
        • 1970-01-01
        • 2013-05-16
        • 2012-12-05
        • 1970-01-01
        • 2015-09-01
        • 1970-01-01
        相关资源
        最近更新 更多