generate_series за изменение летнего времени - различные результаты в зависимости от часового пояса сервера - PullRequest
0 голосов
/ 13 ноября 2018

Когда мой сервер postgres находится в часовом поясе Америки / Нью-Йорка или я использую SET SESSION TIME ZONE 'America/New_York', generate_series учитывает изменение летнего времени, и я могу получить нужную эпоху или момент времени, который мне нужен:

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 не учитывает изменение летнего времени:

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)

Обратите внимание, что 11/4 и 11/5 не были скорректированы с учетом изменения летнего времени.

Есть ли способ обойти это без установки часового пояса сеанса при запросе?

Использование postgres 9.6 ...

Ответы [ 2 ]

0 голосов
/ 13 ноября 2018

Вы можете установить часовой пояс автоматически при подключении для определенных пользователей (ALTER USER) или для конкретной базы данных (ALTER DATABASE).

Единственный другой способ, о котором я могу думать, - это функция.

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;

Производит:

    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)
0 голосов
/ 13 ноября 2018

Часовой пояс сеанса - это то, что контролирует интерпретацию интервала в 1 день, поэтому я думаю, что ответом на ваш вопрос будет просто, нет.

Документы Postgres объясняют это какследует:

При добавлении значения интервала к (или вычитанию значения интервала) из временной метки со значением часового пояса компонент дней увеличивает или уменьшает дату временной метки с помощью часового пояса на указанное числодней.В зависимости от изменения летнего времени (когда часовой пояс сеанса установлен на часовой пояс, который распознает летнее время), это означает, что interval '1 day' не обязательно равно interval '24 hours'.Например, если для часового пояса сеанса задано значение CST7CDT, timestamp with time zone '2005-04-02 12:00-07' + interval '1 day' будет выдавать timestamp with time zone '2005-04-03 12:00-06', а при добавлении interval '24 hours' к той же начальной отметке времени с часовым поясом будет получено timestamp with time zone '2005-04-03 13:00-06', так как в летнее время происходит изменениев 2005-04-03 02:00 в часовом поясе CST7CDT.

Насколько мне известно, нет другого механизма, как сказать интервал для интерпретации в конкретном часовом поясе, кроме установки этогов качестве часового пояса сеанса.Другими словами, я думаю, что вы будете искать что-то вроде '1 day tz America/New_York'::interval, и я не верю, что такой синтаксис существует.

...