"date_part ('epoch', now () в часовом поясе 'UTC')" не совпадает с "now () в часовом поясе" UTC "в postgresql - PullRequest
3 голосов
/ 12 апреля 2010

Я пишу веб-интерфейс в базу данных (PHP / Postgresql), в которой мне нужно хранить различные даты / время. Предполагается, что времена всегда вводятся на стороне клиента по местному времени, а также отображаются по местному времени. В целях хранения я храню все даты / время в виде целых чисел (меток времени UNIX) и нормализуем к UTC. Одно конкретное поле имеет ограничение, что заполненная временная метка не должна быть в будущем, поэтому я попробовал это с ограничением базы данных ...

CONSTRAINT not_future 
    CHECK (timestamp-300 <= date_part('epoch', now() at time zone 'UTC'))

Параметр -300 дает 5-минутную задержку в случае немного рассинхронизированного времени между браузером и сервером. Проблема в том, что это ограничение всегда не выполняется при отправке текущего времени. Я прошел тестирование и обнаружил следующее.

В клиенте PostgreSQL:

SELECT now() - возвращает правильное местное время

SELECT date_part('epoch', now()) - возвращает метку времени Unix в UTC (проверяется путем подачи значения в функцию даты в PHP, корректирующего его компенсацию в моем часовом поясе)

SELECT date_part('epoch', now() at time zone 'UTC') - возвращает метку времени Unix с двумя смещениями часового пояса на запад, например, Я нахожусь в GMT + 2, я получаю метку времени GMT-2.

Очевидно, я понял, что удаление «в часовом поясе« UTC »решит мою проблему, но мой вопрос в том, что« epoch »должен возвращать метку времени Unix, которую AFAIK всегда должен иметь в UTC, почему «эпоха» времени в UTC будет исправлена? Это ошибка, или я что-то упустил из-за определенного / нормального поведения здесь.

1 Ответ

4 голосов
/ 12 апреля 2010

Значение now () в часовом поясе 'UTC' - это ваше текущее время, переведенное в UTC, а затем преобразованное в TIMESTAMP БЕЗ ВРЕМЕННОЙ ЗОНЫ .

Таким образом, вы даете "date_part" TIMESTAMP БЕЗ ВРЕМЕННОЙ ЗОНЫ (неизвестный часовой пояс, другими словами) и ожидаете получить разницу в секундах между ним и фиксированной временной отметкой в ​​известном часовом поясе ("EPOCH", 1970-01- 01 00:00:00 UTC).

Для расчета Postgres требуется TIMESTAMP WITH TIME ZONE. Таким образом, он преобразует ваше значение в часовой пояс UTC , предполагая, что он находится в вашем часовом поясе , и вычисляет разницу.

Что-то вроде:

select ((now() at time zone 'UTC') at time zone '<your_time_zone>') at time zone 'UTC';
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...