仅在UTC 2:00时检索时间戳(带时区)行的SQL查询,而不考虑夏令时
我相信这个标题可能会让人困惑。在标题中找不到这样一个好的词而不把它写得很长 简言之 我有一个PSQL数据库表,它每15分钟归档一个外部API端点。该表包含以下列:仅在UTC 2:00时检索时间戳(带时区)行的SQL查询,而不考虑夏令时,sql,postgresql,Sql,Postgresql,我相信这个标题可能会让人困惑。在标题中找不到这样一个好的词而不把它写得很长 简言之 我有一个PSQL数据库表,它每15分钟归档一个外部API端点。该表包含以下列: id(序列号) 匹配(jsonb) 快照时间(时区为not null的时间戳默认值现在为() 我需要一个SQL查询,该查询将仅获取以下约束下的行: 这一天必须是星期六(6) 时间戳必须位于ISO8601的“…T02:00:00Z” 在指定的开始日期和结束日期之间 我目前拥有的 SELECT id,snapshot_time,m
- id(序列号)
- 匹配(jsonb)
- 快照时间(时区为not null的时间戳默认值现在为()
- 这一天必须是星期六(6)
- 时间戳必须位于ISO8601的“…T02:00:00Z”
- 在指定的开始日期和结束日期之间
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;
(例如,开始和结束时间当前是硬编码的)
问题
这将返回正确的行,但问题是,由于快照_time
列是带时区的时间戳类型,因此产生的行实际上与我居住在东部标准时间间隔5小时
它返回的一个示例行是
id | snapshot_time | ?column?
--------+-------------------------------+--------------------------------------------
120941 | 2016-12-03 02:00:03.32946-05 | {"red": 3389, "blue": 1962, "green": 2911}
如您所见,快照时间确实是2:00,但它是在美国东部时间
我想,“嘿,我可以把时间定在21小时,一周中的第五天(星期五)”,这样就行了,但突然之间,由于未来的夏令时,时间会缩短一个小时
另一件事是使用不带时区的时间戳存储信息
,但随后发生的事情是将2016-12-03T17:44:21-05
切掉-05
,并在数据库中插入新行时将其保留为2016-12-03T17:44:21Z
那么,有没有什么好方法可以创建一个SQL查询,使我能够按照上面列出的要求获取行,而不必担心夏令时?谢谢
这将返回正确的行,但问题是,由于snapshot_time列的类型为timestamp with time zone,因此产生的行实际上与我居住在东部标准时间间隔5小时
时间戳始终以UTC格式存储在PostgreSQL中
对于带有时区的时间戳,内部存储的值始终以UTC(通用协调时间,传统上称为格林威治标准时间,GMT)为单位。指定了明确时区的输入值将使用该时区的适当偏移量转换为UTC。如果输入字符串中未说明时区,则假定它位于系统时区参数指示的时区中,并使用时区的偏移量转换为UTC
当输出带有时区值的时间戳时,它总是从UTC转换为当前时区,并在该时区中显示为本地时间。要查看另一时区中的时间,请更改时区或使用AT时区结构(请参阅)
这将返回正确的行,但问题是,由于snapshot_time列的类型为timestamp with time zone,因此产生的行实际上与我居住在东部标准时间间隔5小时
时间戳始终以UTC格式存储在PostgreSQL中
对于带有时区的时间戳,内部存储的值始终以UTC(通用协调时间,传统上称为格林威治标准时间,GMT)为单位。指定了明确时区的输入值将使用该时区的适当偏移量转换为UTC。如果输入字符串中未说明时区,则假定它位于系统时区参数指示的时区中,并使用时区的偏移量转换为UTC
当输出带有时区值的时间戳时,它总是从UTC转换为当前时区,并在该时区中显示为本地时间。要查看另一时区中的时间,请更改时区或使用AT时区结构(请参阅)
如果有人在谷歌上遇到这个问题,请回答我的问题
根据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;
可能在分钟日期部分没有必要,但要保持一致。回答我的问题,以防有人在谷歌上遇到这个问题
根据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;
分钟日期部分可能不需要,但希望保持一致。虽然我知道您可能没有此选项,但请理解,最佳做法是首先始终以UTC格式存储日期时间数据。如果这样做了,这个问题就不会出现。即使是现在,如果我有选择的话,我也会认真研究将数据库中所有现有的本地时区日期时间数据(以及驱动它的代码)转换为UTC。@CharlesBretana在PostgreSQL中存储UTC时区甚至不是一个选择。这就是它们的存储方式。我没有说存储时区,而是说存储UTC的日期时间。不过,我承认我不熟悉PostgreSQL。您是说您无法控制存储在PostGreSQL表的datetime列中的值吗?客户端软件不能存储UTC值而不是本地时间值?不。我是说您只能存储UTC。虽然我知道您可能没有此选项,但请理解,最佳做法是首先始终以UTC存储日期时间数据。如果这样做了,这个问题就不会出现。即使是现在,如果我有选择的话,我也会认真研究将数据库中所有现有的本地时区日期时间数据(以及驱动它的代码)转换为UTC。@CharlesBretana在PostgreSQL中存储UTC时区甚至不是一个选择。这就是它们的存储方式。我没有说存储时区,而是说存储UTC的日期时间。不过,我承认我不熟悉PostgreSQL。你是说你不能控制你存储在datetime列中的值吗