Почему PostgreSQL, по-видимому, принуждает строку с меткой времени к «МЕТКЕ ВРЕМЕНИ С ЧАСОВЫМ ПОЯСОМ» даже без смещения часового пояса?

#postgresql #datetime #timezone

#postgresql #datetime #Часовой пояс

Вопрос:

Я на PostgreSQL версии 11.10, и у TimeZone меня установлено значение . UTC

Когда я говорю select '2021-02-16 17:45 00' at time zone 'America/New_York'; , я получаю 2021-02-16 12:45:00 , что правильно и ожидаемо.

Однако, когда я говорю select '2021-02-16 17:45' at time zone 'America/New_York'; , я получаю тот же результат.

Похоже, что обе строки принудительно привязаны к timestamp with time zone , что кажется мне немного нелогичным в случае последнего. Почему PostgreSQL ведет себя так? Задокументировано ли это в руководстве (я просмотрел следующие места: В ЧАСОВОМ ПОЯСЕ, затем типы даты / времени, а также интерпретация ввода даты / времени и обработка недопустимых или неоднозначных временных меток, все безрезультатно).

Комментарии:

1. Потому что у вас есть TimeZone = UTC then '2021-02-16 17:45 00' и '2021-02-16 17:45' то же самое, что и Postgres, использует TimeZone параметр в качестве tz, когда он не указан.

2. Смотрите здесь Временные метки 8.5.1.3. Метки времени: «PostgreSQL никогда не проверяет содержимое литеральной строки перед определением ее типа и, следовательно, будет рассматривать оба вышеперечисленных параметра как временные метки без часового пояса». Так '2021-02-16 17:45 00' становится '2021-02-16 17:45' .

Ответ №1:

Поскольку для вашего TimeZone параметра установлено значение UTC , любая временная метка без указанного часового пояса будет интерпретироваться как локальная для часового пояса UTC. Поскольку вы запрашиваете, чтобы временная метка интерпретировалась как America/New_York , Postgres сначала интерпретирует временную метку как временную метку UTC, а затем выполняет вычисления для ее преобразования America/New_York .

Обратите внимание, что если вы на самом деле смотрите на типы, отправляемые в Postgres, это не timestamp with timezone принудительно, если вы не укажете это:

 edb=# select pg_typeof('2021-02-16 17:45' at time zone 'America/New_York');
          pg_typeof          
-----------------------------
 timestamp without time zone
(1 row)

edb=# select pg_typeof('2021-02-16 17:45 00' at time zone 'America/New_York');
          pg_typeof          
-----------------------------
 timestamp without time zone
(1 row)

edb=# select pg_typeof('2021-02-16 17:45 00'::timestamptz at time zone 'America/New_York');
          pg_typeof          
-----------------------------
 timestamp without time zone
(1 row)

edb=# select pg_typeof('2021-02-16 17:45 00'::timestamptz);
        pg_typeof         
--------------------------
 timestamp with time zone
(1 row)

edb=# select pg_typeof('2021-02-16 17:45 00'::timestamp);
          pg_typeof          
-----------------------------
 timestamp without time zone
(1 row)