postgres - 日期时间自动转换

Posted

技术标签:

【中文标题】postgres - 日期时间自动转换【英文标题】:postgres - date time is automatically converted 【发布时间】:2022-01-09 16:46:16 【问题描述】:

在调试模式下使用 vscode,当我将鼠标悬停在日期字段上时,它显示为下图。

但是当我注销它时,它会转换为

"execution_date":"2021-12-02T20:23:48.322Z"

这是负 7 小时。 该字段作为时间戳存储在 AWS RDS 上的 postgres 数据库中,运行 show timezone; 返回 UTC,我在 GMT+7 时间使用 VSCode。由于日期已更改并用于调用api,因此如何解决此问题,因此返回的结果将不正确。

【问题讨论】:

字段是timestamp 还是timestamp with time zone?使用psql 会为该服务器返回什么show timezone;?添加答案以更新您的问题。 @AdrianKlaver 该字段是时间戳,运行 show timezone; 返回 UTC。调试时将鼠标悬停在 execution_date 字段上时,它显示的日期和时间与存储在数据库中的日期和时间相同,但是当它被注销并用于调用 API 时,它会减少 7 小时。 您现在已经了解了如果您关心时区,为什么不应该使用timestamp。阅读Date/Datetimes 8.5.1.3。时间戳。短版您的datetime 被假定为UTC 进入。回到你的时间:select '2021-12-02T20:23:48.322Z' at time zone 'ICT'; 2021-12-03 03:23:48.322 @AdrianKlaver 但是在调试时为什么它显示的时间与存储在数据库中的时间相同,但是当注销并用于调用 API 时,它得到了负 7 小时。我认为这与我的操作系统或 VSCode 有关吗? @AdrianKlaver 抱歉,不知道为什么,但我无法编辑上述回复。在数据库中它存储为2021-12-03 03:23:48.322,文档指出the resulting value is derived from the date/time fields in the input value, and is not adjusted for time zone.,我正在使用Sequelize,并且生成的查询没有设置任何时区,所以它不应该是负7小时,这是正确的。 【参考方案1】:

这不是一个完整的答案,因为这取决于更多信息。相反,它是对正在发生的事情的解释,可以帮助您排除故障:

set TimeZone = UTC;
show timezone;
 TimeZone 
----------
 UTC
--Show that timestamp is taken at UTC
 select now();
              now              
-------------------------------
 2021-12-05 18:23:38.604681+00

--Table with timestamp and timestamptz to show different behavior.
create table dt_test(id integer, ts_fld timestamp, tsz_fld timestamptz);

--Insert local time 'ICT'
insert into dt_test values (1, '2021-12-03 03:23:48.322+07', '2021-12-03 03:23:48.322+07');

--The timestamp entry ignores the time zone offset, while the timestamptz uses it to rotate to UTC as '2021-12-03 03:23:48.322+07' is same as '2021-12-02 20:23:48.322+00'
select * from dt_test ;
 id |         ts_fld          |          tsz_fld           
----+-------------------------+----------------------------
  1 | 2021-12-03 03:23:48.322 | 2021-12-02 20:23:48.322+00


--timestamp takes the value as at 'ICT' and then rotates it to the current 'TimeZone' UTC. The timestamptz takes the value at UTC at rotates it to 'ICT'
select ts_fld AT TIME ZONE 'ICT', tsz_fld AT TIME ZONE 'ICT' from dt_test ;
          timezone          |        timezone         
----------------------------+-------------------------
 2021-12-02 20:23:48.322+00 | 2021-12-03 03:23:48.322

我猜测在获取 API 值的过程中的某个时间点,代码采用 timestamp 值并使用一些等效程序在数据库或下游应用 AT TIME ZONE 'ICT'

【讨论】:

【参考方案2】:

我发现了问题,这与Sequelize和postgres如何处理timestamp without timezone有关。如果你有和我一样的问题,请参考以下链接:https://github.com/sequelize/sequelize/issues/3000

【讨论】:

这里指出的是,如果您关心时区,您应该使用timestamptz 类型。 @AdrianKlaver 这实际上是一个已经存在的系统。谢谢,从现在开始我会更加注意时间戳。

以上是关于postgres - 日期时间自动转换的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Postgres 和 GraphQL 在特定日期自动触发事件?

Postgres 通过时区转换防止时间戳

将提取的文本字符串转换为 Postgres 中字符串长度不同的日期

sql 使用特定数字(日期)#postgres创建自动增量

在 SQL 中从 POSTGRE/SQL 数据库转换 UTC 时间字段

在 PostgreSQL 中将 Julian 日期转换为时间戳