我正在研究一个系统,我正在尝试最小化时区可能引入的错误,因此我在(postgresql)数据库上使用时间戳字段,但是当我创建记录时,我使用UNIX时代的秒数当我读取记录时(使用EXTRACT(EPOCH)
阅读,插入时使用TO_TIMESTAMP()
)。
这样我就可以摆脱时区问题。或者我不过。在挖掘了一点之后我发现postgresql在从表中读取值时会有点困惑。请考虑以下问题:
select current_timestamp, extract(EPOCH from current_timestamp), id, last_gps_read,
extract(EPOCH from current_timestamp) - extract(EPOCH
from last_gps_read) from sometable where id=1
哪个给出了
now | date_part | id | last_gps_read | ?column?
-------------------------------+------------------+----+--------------------------+-----------------
2018-03-21 23:26:07.263931-06 | 1521696367.26393 | 1 | 2018-03-21 23:26:00.5273 | 21606.736631155
注意日期彼此之间的距离非常接近(只有大约7秒的差异?)。
所以,当我使用extract(EPOCH from x)
技巧时,虽然差异会给我7秒钟......而是我得到~21607(我在GMT-6上,这就解释了为什么它是一些21600秒的差异)。这绝对不是很酷,因为这意味着当报告两个日期的UNIX纪元以来的秒数时,它会在报告来自表格的数据的秒数时以某种方式引入时区(我刚刚检查过,因为current_timestamp的UNIX纪元以来的秒数是正确的)。
这是什么理由?因为它听起来很像我的错误。
PS我可以考虑更改DB上的字段类型以使用整数来保存自UNIX纪元以来的实际秒数,所以我绝对摆脱了这一点,但这听起来有点矫枉过正。
答案 0 :(得分:1)
不同之处在于EXTRACT(EPOCH FROM ...)
始终计算相对于GMT时间(众所周知的01.01.1970 00:00:00+00
)的时间。如果将当前时间 转换为GMT,您将获得时间戳2018-03-21 17:26:00.5273+00
,其差异为6小时至约7秒,或约{{1来自GPS时间戳。
您可以将GPS时间转换为当地时间,或者从时间戳差异中减去6 * 3600 + 7 = 21607
以获得所需的结果。
答案 1 :(得分:0)
匹配您的时区:
t=# set timezone to 'GMT+6';
SET
你做了什么:
t=# with c("ct", last_gps_read) as (values('2018-03-21 23:26:07.263931-06'::timestamptz,'2018-03-21 23:26:00.5273'::timestamp))
select ct
, extract(EPOCH from ct)
, last_gps_read
, extract(EPOCH from ct) - extract(EPOCH from last_gps_read)
from c;
ct | date_part | last_gps_read | ?column?
-------------------------------+------------------+--------------------------+-----------------
2018-03-21 23:26:07.263931-06 | 1521696367.26393 | 2018-03-21 23:26:00.5273 | 21606.736631155
(1 row)
你应该做什么:
t=# with c("ct", last_gps_read) as (values('2018-03-21 23:26:07.263931-06'::timestamptz,'2018-03-21 23:26:00.5273'::timestamp))
select ct
, extract(EPOCH from ct)
, last_gps_read
, extract(EPOCH from ct - last_gps_read)
from c;
ct | date_part | last_gps_read | date_part
-------------------------------+------------------+--------------------------+-----------
2018-03-21 23:26:07.263931-06 | 1521696367.26393 | 2018-03-21 23:26:00.5273 | 6.736631
(1 row)
原因:您将double precision
与double precision
分开并获得epoch aware of time zone
- epoch not aware of timezone
。所以你的结果是预期的。并且documented。我建议做的是使用interval
进行时间戳划分,无论是否知道时区(因为区间同时操作),然后从interval
中提取时期。这样您就不需要调整时区或将时区与时区统一为AT TIME ZONE 'GTM'
或其他......