2015-01-13 1 views
1

PostgreSQL 9.3/PostgreSQL-9.3-1100-jdbc41.jarjOOQ Отметка хранится с локальным Timezone смещением

У меня есть таблица со столбцом типа timezone without time zone, это порождает мой объект с действующим java.util.Timestamp собственности.

Что я вижу во время вставки, это процесс привязки jOOQs, преобразующий java.util.Timestamp в дату с локальным смещением часового пояса.

например, для отметки времени unix 1421109419 (13 янв 2015 00:36:59 по Гринвичу) свойство установлено с new Timestamp(1421109419 * 1000).

из регистратора jOOQ я вижу:

2015-01-13 14:14:31,482 DEBUG [http-bio-8002-exec-4] org.jooq.tools.LoggerListener#debug:255 - -> with bind values  : insert into "foo"."bar" ("start_date") values (timestamp '2015-01-13 13:36:59.0') returning "foo"."bar"."id" 

2015-01-13 14:14:31,483 TRACE [http-bio-8002-exec-4] org.jooq.impl.DefaultBinding#trace:179 - Binding variable 3  : 2015-01-13 13:36:59.0 (class java.sql.Timestamp) 

и достаточно в записи уверен, значение "2015-01-13 13:36:59".

Программное обеспечение работает на машине в NZDT, что объясняет смещение +13.

Учитывая, что время предоставляется в агностическом контейнере TimeZone (отметка времени), я ожидал, что это будет выполнено при создании инструкции insert.

Как я могу создать временные метки jOOQ не по местному времени?

+0

Итак, у вашей модели домена есть поля «Timestamp», которые определены непосредственно? Так что это не происходит через jOOQ Converter http://www.jooq.org/doc/3.5/manual/sql-execution/fetching/data-type-conversion/? – Alex

+0

Правильно - 'java.util.Timestamp' - это то, что генерируется jOOQ и заполняется мной. Нет промежуточных преобразователей. – markdsievers

+0

Я вижу несколько ссылок на драйвер PostgreSQL, являющийся причиной этого. Если это так, существует ли какой-либо метод в jOOQ, который я могу использовать для ввода временных меток в зависимости от значения эпохи, например, 'TIMESTAMP WITHOUT TIME ZONE 'epoch' + 1421109419 * INTERVAL '1 second''? – markdsievers

ответ

3

К сожалению, у вас есть несколько вещей, которые работают против вас:

  1. Драйвер PostgreSQL JDBC устанавливает часовой пояс для вашей виртуальной машины Java часовой пояс в сеансе Postgres. Поэтому, даже если ваш сервер баз данных работает в UTC, поле TIMESTAMP будет вставлено с использованием часового пояса вашей JVM. Когда вы вставляете или запрашиваете данные, сервер базы данных всегда будет использовать часовой пояс JVM.
  2. Вы используете TIMESTAMP вместо TIMESTAMPTZ. Описание этих типов не отражает их фактическое использование. TIMESTAMPTZ на самом деле означает агностик часовой пояс. Независимо от того, какое значение вы вставляете, оно будет настроено на UTC, используя часовой пояс сеанса.

Из-за этих двух проблем, если у вас есть два разных JVM: один, использующий время в Лос-Анджелесе, а другой - время в Нью-Йорке - всякий раз, когда вы пишете TIMESTAMP с одной JVM, это будет другое время UTC »в другой JVM. TIMESTAMP принимает скорректированное значение и просто использует его как заданное. Если вы измените свои столбцы TIMESTAMP на TIMESTAMPTZ, то одновременно в обеих JVM всегда будет одинаковое время UTC.

Если вы посмотрите на ConnectionGactoryImpl # OpenConnectionImp драйвера Postgres JDBC, вы увидите, где он устанавливает часовой пояс локального JVM в качестве часового пояса для зоны сеанса сервера базы данных.

Таким образом, единственный разумный способ справиться с этим - использовать TIMESTAMPTZ, а не TIMESTAMP. Вот еще немного информации об этом:

PostgreSQL/JDBC and TIMESTAMP vs. TIMESTAMPTZ

http://justatheory.com/computers/databases/postgresql/use-timestamptz.html

0

Следующая (очень противный) код работает для меня:

eventsRecord.setCreatedOn(new Timestamp(System.currentTimeMillis() 
    - TimeZone.getDefault().getOffset(new Date().getTime()))); 

Увы jOOQ просто использует локальный часовой пояс при сохранении в PostgreSQL «timestamp without timezone» или MySQL «datetime».Исходным кодом для этой пародии является here, она не указывает часовой пояс и не имеет возможности для пользователя переопределить эту функцию и указать часовой пояс. Это делает использование этого очень базового типа данных из jOOQ совершенно бесполезным, с множеством клиентов, все с разными часовыми поясами, записывая данные в одно и то же поле, не записывая свой часовой пояс или не нормализуя данные в UTC.

JDBC предоставляет дополнительную информацию о three-argument setTimestamp, где пользователь может указать желаемый часовой пояс (UTC - это в основном единственное значение, которое имеет смысл). Однако jOOQ «абстрагирует» от JDBC и не предлагает этого средства.

 Смежные вопросы

  • Нет связанных вопросов^_^