Как отключить преобразование в UTC при хранении OffsetDateTime в PostgreSQL - PullRequest
0 голосов
/ 30 августа 2018

Учитывая эту таблицу:

CREATE TABLE a(
  t TIMESTAMP WITH TIME ZONE
);

И этот простой фрагмент кода JDBC:

DriverManager.getConnection(
    "jdbc:postgresql://localhost:5432/dbname", "user", "password"
).use { connection ->
    val nowSomeTimeZone = OffsetDateTime.now(ZoneOffset.of("+4"))
    connection.prepareStatement("insert into a(t) values (?)").use { insertStmt ->
        insertStmt.setObject(1, nowSomeTimeZone)
        insertStmt.executeUpdate()
    }
    connection.createStatement().use { stmt ->
        stmt.executeQuery("select * from a").use { resultSet ->
            resultSet.next()
            val t = resultSet.getObject(1, OffsetDateTime::class.java)
            println("$nowSomeTimeZone -> $t")
        }
    }
}

Где-то внутри стека JDBC должно происходить автоматическое преобразование из +04: 00 в UTC, потому что это вывод println:

2018-08-30T10:35:33.594+04:00 -> 2018-08-30T06:35:33.594Z

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

$ psql -h localhost -U username
dbname=> select * from a;
             t              
----------------------------
 2018-08-30 08:35:33.594+02

Почему происходит это преобразование и как его отключить?

1 Ответ

0 голосов
/ 30 августа 2018

Отключение преобразования невозможно, поскольку сервер PostgreSQL извлекает информацию о часовом поясе и всегда сохраняет временные метки в формате UTC, даже если вы явно используете тип TIMESTAMP WITH TIME ZONE.

Цитирование документации PostgreSQL :

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

Кроме того, в документации говорится:

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

Странное поведение, описанное в вопросе, заключается в том, что

  • Драйвер JDBC всегда возвращает метку времени в UTC
  • Консольный клиент psql преобразует временную метку в местный часовой пояс пользователя перед его отображением, в данном случае немецкое время (+02: 00)

Спасибо @RobbyCornelissen за идеи.

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