LocalDateTime and SQL Server JDBC 4.2 driver
I don't know what I'm doing wrong here.
You're not doing anything wrong. You have encountered a deficiency in Microsoft's JDBC driver for SQL Server prior to version 7.1.0, discussed here.
If you are using mssql-jdbc version 7.1.0 or later then you can use getObject(x, LocalDateTime.class)
as expected.
For mssql-jdbc versions prior to 7.1.0, as others have suggested, you'll need to retrieve a Timestamp
and convert it to a LocalDateTime
. However, be aware that the simplistic solution ...
LocalDateTime dateTime = resultSet.getTimestamp("date_from").toLocalDateTime()
... will corrupt certain date/time values if the default time zone for the JVM observes Daylight Saving Time, a.k.a. "Summer Time". For example,
// time zone with Daylight Time
TimeZone.setDefault(TimeZone.getTimeZone("America/Edmonton"));
// test environment
Statement st = conn.createStatement();
st.execute("CREATE TABLE #tmp (id INT PRIMARY KEY, dt2 DATETIME2)");
st.execute("INSERT INTO #tmp (id, dt2) VALUES (1, '2018-03-11 02:00:00')");
ResultSet rs = st.executeQuery("SELECT dt2 FROM #tmp WHERE id=1");
rs.next();
// test code
LocalDateTime x = rs.getTimestamp("dt2").toLocalDateTime(); // bad
System.out.println(x.toString());
will print "2018-03-11T03:00". Note that the time is "03:00", not "02:00".
Instead, you'll need to retrieve the Timestamp
as UTC and then convert it into a LocalDateTime
for UTC, thus removing the time zone component
// time zone with Daylight Time
TimeZone.setDefault(TimeZone.getTimeZone("America/Edmonton"));
// test environment
Statement st = conn.createStatement();
st.execute("CREATE TABLE #tmp (id INT PRIMARY KEY, dt2 DATETIME2)");
st.execute("INSERT INTO #tmp (id, dt2) VALUES (1, '2018-03-11 02:00:00')");
ResultSet rs = st.executeQuery("SELECT dt2 FROM #tmp WHERE id=1");
rs.next();
// test code
Timestamp ts = getTimestamp("dt2", Calendar.getInstance(TimeZone.getTimeZone("UTC")));
LocalDateTime x = LocalDateTime.ofInstant(ts.toInstant(), ZoneId.of("UTC")); // good
System.out.println(x.toString());
which prints "2018-03-11T02:00".
This is because the Microsoft SQL Server JDBC driver implementation of resultSet.getObject(...)
cannot auto convert from java.sql.Timestamp
to LocalDateTime
.
As a workaround you can get the value as java.sql.Timestamp
and then convert java.sql.Timestamp
to LocalDateTime
by using: java.sql.Timestamp.toLocalDateTime()
LocalDateTime dateTime = resultSet.getTimestamp("date_from").toLocalDateTime()