SQL Query仅在夏令时2:00检索带时间戳(带时区)的行,而不考虑夏令时

时间:2016-12-27 23:26:10

标签: sql postgresql

我确定标题可能令人困惑。无法在标题中找到一种方法来说明这一点,而不是非常长。

简而言之

我有一个PSQL数据库表,每隔15分钟存档一个外部API端点。该表格包含以下列:

  • id(serial)
  • 匹配(jsonb)
  • snapshot_time(带时区的时间戳不为null now now())

我需要一个只在以下约束下获取行的SQL查询:

  • 这一天必须是星期六(6)
  • 时间戳必须位于' ... T02:00:00Z' ISO8601
  • 指定的开始日期和结束日期之间。

我目前拥有什么

SELECT id,snapshot_time,match->'kills' FROM match_archive 
WHERE extract(dow from snapshot_time)=6 
AND snapshot_time >= '2016-12-01' 
AND date_part('hour', snapshot_time)=2 
AND date_part('minute', snapshot_time)=00;

(例如,开始和结束时间目前是硬编码的)

问题

这会返回正确的行,但问题是,snapshot_timetimestamp with time zone后的结果行实际上是因为我住在东部标准时间以来已经过了5个小时。

它返回的示例行是

   id   |         snapshot_time         |                  ?column?
--------+-------------------------------+--------------------------------------------
 120941 | 2016-12-03 02:00:03.32946-05  | {"red": 3389, "blue": 1962, "green": 2911}

正如您所看到的,snapshot_time确实是2:00,但它在EST中。

我想,"嘿,我可以按小时计算:21,星期几:5(星期五)",这样可行,但突然之间它已经过了一小时到将来的夏令时。

另一件事是使用timestamp without time zone存储信息,但接下来会发生的事情是2016-12-03T17:44:21-05只需切断-05并在插入时将其保留为2016-12-03T17:44:21Z数据库中的新行。

那么,有没有什么好方法可以让SQL查询按照上面列出的要求获取行而不用担心夏令时?感谢。

2 个答案:

答案 0 :(得分:2)

  

这会返回正确的行,但问题是,自snapshot_time列以来的结果行是带时区的类型时间戳实际上是因为我住在东部标准时间以来已经过了5个小时。

时间戳始终以UTC格式存储在PostgreSQL中,per the docs

  

对于带时区的时间戳,内部存储的值始终为UTC(通用协调时间,传统上称为格林威治标准时间,GMT)。具有指定显式时区的输入值将使用该时区的适当偏移量转换为UTC。如果输入字符串中未指定时区,则假定它位于系统的TimeZone参数指示的时区中,并使用时区的偏移量转换为UTC。

     

当输出带有时区值的时间戳时,始终从UTC转换为当前时区区域,并在该区域中显示为本地时间。要查看其他时区的时间,请更改时区或使用AT TIME ZONE构造(参见Section 9.9.3)。

答案 1 :(得分:0)

如果有人在Google上遇到此问题,请回答我的问题。

根据Evan Carroll的回答,以下SQL解决了我的问题:

SELECT id,snapshot_time,match->'kills' FROM match_archive 
WHERE extract(dow from snapshot_time AT TIME ZONE 'UTC')=5 
AND snapshot_time >= '2016-12-01' 
AND date_part('hour', snapshot_time AT TIME ZONE 'UTC')=2 
AND date_part('minute', snapshot_time AT TIME ZONE 'UTC')=00;

可能在分钟date_part上没有必要,但希望保持一致。