UT C отличается на 2 серверах для одной и той же базы данных - PullRequest
0 голосов
/ 05 мая 2020

У меня есть один сервер, который работает по времени UT C, а другой - по EST. Теперь я скинул базу данных из UT C и импортировал в EST. Поскольку временные метки всегда сохраняются как UT C, я не могу найти причину, по которой я получаю два разных результата для одного и того же запроса:

выберите report_on в часовом поясе 'UT C', температура из данных в порядке report_on desc;

UT C Сервер:

 temperature |                device                |          timezone          
-------------+--------------------------------------+----------------------------
        17.2 | ------------------------------------ | 2020-05-05 12:13:16.256+00

EST Сервер:

 temperature |                device                |          timezone          
-------------+--------------------------------------+----------------------------
        17.2 | ------------------------------------ | 2020-05-05 14:13:16.256+02

Что мне здесь не хватает? Как я могу запросить данные без часовых поясов, мне нужно время UT C, а не время +02? Как я могу этого добиться?

Изменить: я добавил строки через nodejs:

INSERT INTO data(device, reported_on, temperature, humidity) VALUES($1, to_timestamp(' + Date.now() /1000.0 + '), $2, $3) RETURNING *

Тип столбца: report_on TIMESTAMP,

Обновление: Изменение часового пояса устранило проблему!

ALTER DATABASE sensors SET timezone TO 'UTC';
SELECT pg_reload_conf();

Ответы [ 3 ]

1 голос
/ 06 мая 2020

Утверждение «временные метки всегда сохраняются как UT C» неверно. Метка времени без времени (метка времени) сохраняется с местным временем, метка времени с часовым поясом (timestamptz) всегда сохраняется в UT C. Из документации :

метка времени без часового пояса, PostgreSQL будет игнорировать любые указания часового пояса. То есть результирующее значение получается из полей даты / времени во входном значении и не корректируется для часового пояса.

Для метки времени с часовым поясом внутреннее сохраненное значение всегда находится в UT C (Универсальное координированное время, традиционно известное как среднее время по Гринвичу, GMT). Входное значение, для которого явно указан часовой пояс, преобразуется в UT C с использованием соответствующего смещения для этого часового пояса. Если во входной строке не указан часовой пояс, то предполагается, что он находится в часовом поясе, указанном системным параметром TimeZone, и преобразуется в UT C с использованием смещения для часового пояса.

Дополнительно будьте очень осторожны при использовании 'EST' или любых других сокращений часовых поясов, вместо этого используйте полное имя часового пояса . Аббревиатуры указывают на фиксированное смещение UT C (т.е. EST всегда UT C -5, а EDT всегда UT C -4) и не распознают переход на летнее время (DST). С другой стороны, полные имена (например, US / Central или America / Montreal или любое другое полное название часового пояса) учитывают DST и соответственно корректируют смещение UT C.

В отличие от сокращений, показанных в pg_timezone_abbrevs, многие из этих имен подразумевают набор правил перехода на летнее время.

Вы можете наблюдать это с помощью:

select * from pg_timezone_abbrevs where abbrev in ('EDT', 'EST')
select * from pg_timezone_names  where name in ('US/Eastern','America/New_York','America/Montreal')
1 голос
/ 05 мая 2020

Это касается конфигурации вашей локальной базы данных. Я создал фиктивную базу данных локально, и результат был следующим:

test=# CREATE TABLE timestamptest (timezone TIMESTAMPTZ);`

Показал мой шаблон часового пояса:

test=# SHOW TIMEZONE;
 TimeZone 
----------
 UTC
(1 row)

И вставил некоторые значения внутрь:

test=# SELECT * FROM timestamptest;
           timezone            
-------------------------------
 2020-05-05 15:26:27.377549+00
 2020-05-05 15:28:14.014597+00
(2 rows)

Теперь я изменил переменную локального часового пояса:

test=# SET TIME ZONE 'America/Montreal';
SET

И снова выбрал информацию:

test=# INSERT INTO timestamptest VALUES (now());
INSERT 0 1
test=# SELECT * FROM timestamptest ;
           timezone            
-------------------------------
 2020-05-05 11:26:27.377549-04
 2020-05-05 11:28:14.014597-04
(2 rows)

И мой часовой пояс отличается, потому что команда SET:

test=# SHOW timezone;
     TimeZone     
------------------
 America/Montreal
(1 row)

Вы можете изменить свою локальную конфигурацию, и, что касается выбранных вами вариантов, показанных в вашем вопросе, импорт кажется правильным, просто необходимо установить локальную конфигурацию метки времени равной от одного к другому.

Обратите внимание, что -04 в конце метки времени показывает, что ваше время изменилось на 4 часа по сравнению с -00 изначально. Просто форматирование.

Дополнительная информация здесь: здесь postgresql документы

0 голосов
/ 05 мая 2020

Тип столбца: TIMESTAMP* "

Думаю, в этом ваша проблема. Вы хотите, чтобы использовал TIMESTAMP WITH TIME ZONE Вместо этого . В качестве альтернативы, не используйте AT TIME ZONE 'UTC' в своем операторе SELECT, чтобы вы просто вернули ту же временную метку, которая была сохранена, независимо от часового пояса.

Что происходит в SELECT reported_on AT TIME ZONE 'UTC' заключается в том, что сохраненная дата конвертируется из местного часового пояса базы данных в UT C. В вашей второй базе данных с другим местным часовым поясом это другое преобразование, приводящее к смещению в результате.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...