Я столкнулся с проблемой, когда MySQL хранит разные значения даты и времени, чем передает клиент. Сервер работает в формате UTC, а клиент — в другом часовом поясе. Каким-то образом MySQL, кажется, преобразует значения даты и времени между часовым поясом клиента и сервера, хотя типы SQL DATE
, TIME
и TIMESTAMP
не имеют часового пояса. Ни одна другая база данных, которую я тестировал до сих пор, не имеет такого поведения.
Для воспроизведения проблемы можно использовать следующий код. Когда сервер работает в формате UTC, код работает только тогда, когда клиент также работает в формате UTC.
try (Connection connection = this.dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(
"SELECT ? = DATE '1988-12-25', ? = TIME '15:09:02', ? = TIMESTAMP '1980-01-01 23:03:20'")) {
preparedStatement.setDate(1, java.sql.Date.valueOf("1988-12-25"));
preparedStatement.setTime(2, java.sql.Time.valueOf("15:09:02"));
preparedStatement.setTimestamp(3, java.sql.Timestamp.valueOf("1980-01-01 23:03:20"));
try (ResultSet resultSet = preparedStatement.executeQuery()) {
while (resultSet.next()) {
System.out.println(resultSet.getBoolean(1));
System.out.println(resultSet.getBoolean(2));
System.out.println(resultSet.getBoolean(3));
}
}
}
я использую
- MySQL 5.7.14
- mysql-коннектор-java 6.0.5
- Oracle Java 1.8.0_131
Мой URL-адрес JDBC просто jdbc:mysql://host:port/database
изменить
Мои рассуждения о том, почему часовые пояса не должны играть здесь роли и не должно происходить преобразование часовых поясов, двояки. Во-первых, на уровне SQL TIMESTAMP
является псевдонимом для TIMESTAMP WITHOUT TIME ZONE
, который строго подразумевает, что в отличие от TIMESTAMP WITH TIME ZONE
его значения не имеют часового пояса. Другими словами, значения представляют собой не моменты времени, а скорее локальные значения даты и времени.
Во-вторых, то, что java.sql.Timestamp
находится в часовом поясе JVM, является просто артефактом того, что он является подклассом java.util.Date
. (Я знаю, что java.util.Date
не имеет часового пояса). В Javadoc из java.sql.Timestamp
из совершенно ясно, что отношения предназначены только для целей реализации.
Я чувствую, что оба эти утверждения подтверждаются тем фактом, что в Java SE 8/JDBC 4.2 java.sql.Timestamp
отображается на java.time.LocalDateTime
, а не на java.time.ZonedDateTime
или java.time.OffsetDateTime
.
изменить 2
Я не понимаю, почему значения TIMESTAMP
подлежат преобразованию часового пояса. В отличие от TIMESTAMP WITH TIME ZOONE
, это "локальные" значения, не связанные с часовым поясом, и поэтому к ним не должно применяться преобразование часовых поясов.
Calendar
для указания часового пояса. - person Mick Mnemonic   schedule 22.04.2017