2013-06-27 4 views
2

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

В этой связи я в настоящее время есть проблема, связанная с различными временными метками в приложении Java, хранящемся в базе данных PostgreSQL.

Для хранения вещей простых, предположит, имеющие следующую таблицу:

CREATE TABLE ts_test 
(
    id integer NOT NULL, 
    utc timestamp without time zone, 
    local timestamp with time zone, 
    CONSTRAINT pk PRIMARY KEY (id) 
) 

Итак, я должен хранить время UTC штамп и местные один, который в моем случае является центральной Европой летнего времени, поэтому в настоящее время UTC +2.

Далее предположим, с 2 записей в таблице, которая выводится на консоль Psql следующим образом (база данных работает в формате UTC):

# select id, utc, local, local-utc as diff from ts_test; 
id |   utc   |   local   | diff 
----+---------------------+------------------------+---------- 
    1 | 2012-06-27 12:00:00 | 2012-06-27 12:00:00+00 | 00:00:00 
    2 | 2012-06-27 12:00:00 | 2012-06-27 14:00:00+00 | 02:00:00 
(2 rows) 

Теперь возникает несколько вопросов:

  • Что именно означает ли вывод в локальном столбце?
  • Как система знает часовой пояс, я вставил значение в?
  • Как я могу увидеть реальное необработанное значение (например, миллисекунды)?

Я предположил бы, что местная «12: 00: 00 + 00» первой линии означает, что в UTC - 12:00, а в 14:00 - в CEST. Но кажется (и так мне сказал наш администратор базы данных), что локальная «14: 00: 00 + 00» 2-й строки является правильным значением для 14:00 CEST, которое поддерживается разницей в 2 часа.

Но для получения 2-й линии с помощью SQL вставки, я должен написать

insert into ts_test (id, utc, local) values (2, '2012-06-27 12:00:00', '2012-06-27 16:00:00+02'); 

, который снова не поддерживает предикации.

Итак, чтобы подвести итог этому длинному вопросу - может ли кто-нибудь просветить меня о том, как все это работает подробно, что должен означать вывод и как следует правильно писать локальные метки времени в базу данных? .

+0

Часть '+ 00' - это замороженное смещение временной зоны. Вероятно, вы хотите записать фактическое имя часового пояса. Любой регион, который соблюдает DST, будет переходить из одного «часового пояса» в другой в течение года. В любом случае ваше местное время хранится как нулевое смещение, что означает UTC, что неверно. Более подробная информация содержится в документации по дате/времени Postgres (http://www.postgresql.org/docs/9.2/static/datatype-datetime.html). – tadman

+0

@tadman: Спасибо за подсказку. Я уже рассматривал документацию PostgresQL, но пока не могу ответить на мою проблему. - Согласно странице, на которую вы ссылаетесь, она говорит, что временные метки всегда хранятся в формате UTC, но выводятся в конкретном часовом поясе.Итак, это одна из проблем, когда моя база данных работает в UTC, хотя я пишу локальные даты в CEST? Когда я изменяю параметр часового пояса на «Европа/Берлин», я получаю вывод +2 для всех местных жителей и разностей. Это снова поддержало бы мое предположение выше для 1-й линии, но мне сказали, что 2-я строка верна. * все еще озадачен * –

+0

Тип столбца - это «временная метка с часовым поясом * смещение *», так как фактическая часовая зона, которая дала это смещение, не записывается. Есть много часовых поясов, которые являются UTC + 2 в разное время года. – tadman

ответ

1

По выходу local колонки, часовой пояс SQL сессии устанавливается в UTC или GMT и не часовой пояс, где вы живете в Предположительно, это то, что вы имеете в виду: база данных работает в UTC. Это корень проблемы, но давайте попробуем разобраться.

Сам db, как хранилище данных, не имеет часового пояса, но каждый сеанс SQL имеет свой часовой пояс.

Когда они просили на SQL сессии значения timestamp without time zone являются не поворачиваются в часовом поясе сеанса и не представлены с временным сдвигом, в то время как значения для timestamp with time zone поворачиваются часового пояса сеанса и представленное временным смещением для этого часового пояса. В этом разница между ними.

Часовой пояс никогда не хранится ни в одном из типов данных, потому что при чтении значения все, что имеет значение, является часовым поясом SQL-сессии, запрашивающей это значение.

Настройка ваш SQL часовой пояс для UTC не является хорошей идеей, потому что она противоречит этому другую часть вопроса:

Итак, я должен хранить время UTC штамп и местный один, который в моем дело занимает центральное место в Европе летнее время, поэтому в настоящее время UTC + 2

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

Также обратите внимание, что при хранении в то же время в utc timestamp without time zone и local timestamp with time zone не имеет смысла, потому что вы всегда могли получить utc с:

SELECT local AT TIME ZONE 'UTC' FROM ts_test WHERE... 

EDIT: ответы на вопросы в комментариях:

Вопрос: вы говорите, что если мой часовой пояс установлен на мое местное время в сеансе , тогда я должен увидеть, например ... 14: 00: 00 + 02 в местном для utc значение ... 12:00:00

Да.

В: И при написании чего-либо в локальном поле из моего приложения важно, какой часовой пояс установлен?

Точно.

В: Как установить это в JDBS-сессии?

Я не знаю, JDBC, но на уровне SQL, который был бы, например:

SET timezone='Europe/Berlin'; 

Обычно она автоматически устанавливается из окружающей среды, но он может быть принужден на различных уровнях, включая postgresql.conf. Установка его явно в сеансе отменяет что-либо еще.

Q: я могу видеть необработанное значение метки времени каким-то образом, чтобы убедиться, что это проблема не только представление при отображении

Я не знаю, как сделать это, кроме как с pageinspect который работает на более низком уровне.

+0

Я был уверен, что кто-то скажет, что нет смысла хранить как utc, так и локальные, но, несмотря на то, что я полностью согласен, у меня есть эта ситуация в моем проекте и приходится иметь дело с этим. (И есть причина для того, что находится вне сферы действия здесь.) Что касается вашего замечания с часовым поясом сессии, вы говорите, что если мой часовой пояс установлен на мое местное время в сеансе, то я должен увидеть, например ... 14: 00: 00 + 02 в местном для значения utc ... 12:00:00? И когда вы пишете что-то в локальном поле из моего приложения, важно, какой временной интервал там установлен? Как установить это в JDBS-сессии? –

+0

И могу ли я увидеть необработанное значение временной метки, чтобы убедиться, что это не просто проблема с представлением при отображении? –

+0

@ Geziefer: я обновил ответ –