Postgres 9.6, часовые пояса: почему эти два запроса дают мне разное время - PullRequest
2 голосов
/ 26 сентября 2019

Хорошо, поэтому я всегда был нечетким с часовыми поясами.Я поправляюсь, но пока нет.Можете ли вы, люди, просветить меня?

Контекст: я получаю время UTC от внешнего интерфейса.Например, чтобы обозначить дату 1 September 2019, я получу 2019-08-31 22:00:00Z (мы находимся в Брюсселе, летнее время, отсюда разница в 2 часа).

С этой даты мне нужно сгенерировать серию6 месяцев до этого.Так что это March April May June July August.

Мне удалось найти решение, честно говоря, немного не повезло.Я все еще не уверен, что понимаю детали того, что происходит ниже:

database=> show timezone;
 TimeZone 
----------
 UTC
(1 row)

database=> select generate_series(
        ('2019-08-31 22:00:00Z'::timestamp at time zone 'Europe/Brussels')::date - '6 month'::interval,
        ('2019-08-31 22:00:00Z'::timestamp at time zone 'Europe/Brussels')::date - '1 month'::interval,
        '1 month'::interval
      );
   generate_series   
---------------------
 2019-02-28 00:00:00
 2019-03-28 00:00:00
 2019-04-28 00:00:00
 2019-05-28 00:00:00
 2019-06-28 00:00:00
 2019-07-28 00:00:00
(6 rows)

database=> select generate_series(
        ('2019-08-31 22:00:00Z' at time zone 'Europe/Brussels')::date - '6 month'::interval,
        ('2019-08-31 22:00:00Z' at time zone 'Europe/Brussels')::date - '1 month'::interval,
        '1 month'::interval
      );
   generate_series   
---------------------
 2019-03-01 00:00:00
 2019-04-01 00:00:00
 2019-05-01 00:00:00
 2019-06-01 00:00:00
 2019-07-01 00:00:00
 2019-08-01 00:00:00

Почему я получаю неправильные результаты, если я использую ::timestamp?

1 Ответ

3 голосов
/ 26 сентября 2019

На самом деле есть два разных оператора & ldauo; с именем AT TIME ZONE, один преобразует timestamp with time zone в timestamp without time zone, а другой наоборот.

Если первый аргумент - timestamp with time zone,значение преобразуется в timestamp without time zone, который показывает, что будут настенные часы в этом часовом поясе.

Если первый аргумент - timestamp without time zone, он интерпретируется в часовом поясе сеанса (определяется значениемtimezone) и преобразуется в метку абсолютного времени.

Теперь timestamp with time zone - это предпочтительный тип даты / времени категория типа , поэтомуСтроковый литерал во втором запросе интерпретируется как timestamp with time zone в соответствии с документацией .В первом запросе это timestamp without time zone.Поскольку задействованы разные операторы, неудивительно, что результаты отличаются.

В вашем первом запросе время настенных часов 22:00 интерпретируется так, как будто часы висели в Брюсселе, поэтому на самом деле это 2000:00 UTCПервым аргументом generate_series, с которого начинается подсчет, является 28 февраля 2019 г., 20:00 UTC (перед приведением к date).

...