generate_series over daylight savings change - varied results depending on server timezone
当我的postgres服务器位于America / New_York时区,或者我使用
1 2 3 4 5 6 7 8 9 10 11 12 13 | postgres=# SET SESSION TIME ZONE 'America/New_York'; SET postgres=# postgres=# WITH seq(ts) AS (SELECT * FROM generate_series('2018-11-03 00:00:00.000 -04:00', '2018-11-06 13:40:39.067 -05:00', '1d'::INTERVAL)) postgres-# SELECT ts, EXTRACT(epoch FROM ts) AS epoch, ts at TIME zone 'America/New_York' AS eastern postgres-# FROM seq; ts | epoch | eastern ------------------------+------------+--------------------- 2018-11-03 00:00:00-04 | 1541217600 | 2018-11-03 00:00:00 2018-11-04 00:00:00-04 | 1541304000 | 2018-11-04 00:00:00 2018-11-05 00:00:00-05 | 1541394000 | 2018-11-05 00:00:00 2018-11-06 00:00:00-05 | 1541480400 | 2018-11-06 00:00:00 (4 ROWS) |
但是当我的服务器处于生产中的UTC状态时,generate_series不会考虑夏令时的变化:
1 2 3 4 5 6 7 8 9 10 11 12 | postgres=# SET SESSION TIME ZONE 'UTC'; SET postgres=# WITH seq(ts) AS (SELECT * FROM generate_series('2018-11-03 00:00:00.000 -04:00', '2018-11-06 13:40:39.067 -05:00', '1d'::INTERVAL)) postgres-# SELECT ts, EXTRACT(epoch FROM ts) AS epoch, ts at TIME zone 'America/New_York' AS eastern postgres-# FROM seq; ts | epoch | eastern ------------------------+------------+--------------------- 2018-11-03 04:00:00+00 | 1541217600 | 2018-11-03 00:00:00 2018-11-04 04:00:00+00 | 1541304000 | 2018-11-04 00:00:00 2018-11-05 04:00:00+00 | 1541390400 | 2018-11-04 23:00:00 2018-11-06 04:00:00+00 | 1541476800 | 2018-11-05 23:00:00 (4 ROWS) |
第4/4和第11/5号通知尚未针对DST更改进行调整。
在我查询时没有设置会话时区有什么方法吗?
使用postgres 9.6 ...
会话时区控制如何解释1天的间隔,所以我认为你的问题的答案很简单,没有。
Postgres文档解释如下:
When adding an interval value to (or subtracting an interval value from) a timestamp with time zone value, the days component advances or decrements the date of the timestamp with time zone by the indicated number of days. Across daylight saving time changes (when the session time zone is set to a time zone that recognizes DST), this means
interval '1 day' does not necessarily equalinterval '24 hours' . For example, with the session time zone set toCST7CDT ,timestamp with time zone '2005-04-02 12:00-07' + interval '1 day' will producetimestamp with time zone '2005-04-03 12:00-06' , while addinginterval '24 hours' to the same initial timestamp with time zone producestimestamp with time zone '2005-04-03 13:00-06' , as there is a change in daylight saving time at2005-04-03 02:00 in time zoneCST7CDT .
据我所知,除了将其设置为会话时区之外,没有其他机制可以告诉如何在特定时区内解释间隔。 换句话说,我认为你正在寻找类似
您可以在连接特定用户(ALTER USER)或特定数据库(ALTER DATABASE)时自动设置时区。
我能想到的另一种方法是使用一个函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | BEGIN; CREATE FUNCTION f1() RETURNS SETOF timestamptz AS $$ SELECT generate_series('2018-11-03 00:00:00-04', '2018-11-06 00:00:00-05', INTERVAL '1 day'); $$ LANGUAGE SQL SET timezone = 'America/New_York'; SET timezone = 'UTC'; SELECT generate_series('2018-11-03 00:00:00-04', '2018-11-06 00:00:00-05', INTERVAL '1 day'); SELECT * FROM f1(); ROLLBACK; |
生产:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | generate_series ------------------------ 2018-11-03 04:00:00+00 2018-11-04 04:00:00+00 2018-11-05 04:00:00+00 2018-11-06 04:00:00+00 (4 ROWS) f1 ------------------------ 2018-11-03 04:00:00+00 2018-11-04 04:00:00+00 2018-11-05 05:00:00+00 2018-11-06 05:00:00+00 (4 ROWS) |