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.