I'm running into an issue where MySQL stores different date time values than the client passes. The server runs in UTC and the client in a different time zone. Somehow MySQL seems to convert date time values between the client and server time zone even though the SQL types DATE, TIME and TIMESTAMP all have no time zone. No other database I tested so far has this behaviour.
The following code can be used to reproduce the issue. When the server runs in UTC the code only works when the client also runs in 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));
}
}
}
I'm using
- MySQL 5.7.14
- mysql-connector-java 6.0.5
- Oracle Java 1.8.0_131
My JDBC URL is just jdbc:mysql://host:port/database
edit
My reasoning why time zones should not play a role here and no time zone conversion should happen is two fold. Firstly on the SQL level TIMESTAMP is an alias for TIMESTAMP WITHOUT TIME ZONE which strongly implies that unlike TIMESTAMP WITH TIME ZONE it values have no time zone. In other words values are not instants in time but rather in local date time values.
Secondly that java.sql.Timestamp is in JVM time zone is merely artefact of being a subclass of java.util.Date. (I am aware that java.util.Date has no time zone). The Javadoc of java.sql.Timestamp of makes it quite clear that relationship is only for implementation purposes.
I feel both of these assertions are confirmed by the fact that in Java SE 8 / JDBC 4.2 java.sql.Timestamp is mapped to java.time.LocalDateTime and not java.time.ZonedDateTime or java.time.OffsetDateTime.
edit 2
I do not understand why TIMESTAMP values are subject to time zone conversion. Unlike TIMESTAMP WITH TIME ZOONE These are "local" values and do not have an associated time zone and should therefore have no time zone conversion applied to them.