I am looking for a way to reliably retrieve dates and timestamps from a database using JDBC. The main obstacle I am facing is the fact that a call to ResultSet::getDate
or ResultSet::getTimestamp
modifies the values for dates between 1582-10-5 and 1582-10-14. This seems to be a limitation of java.sql.Date
, which automatically adds 10 days to dates within this range. You can see for yourself by running Date.valueOf(LocalDate.of(1582, 10, 5)).toString()
, which yields 1582-10-15
.
Example
I have created the following table in PostgreSQL to illustrate the issue:
CREATE TABLE dates (date DATE, datetime TIMESTAMP);
INSERT INTO dates VALUES ('1582-10-10', '1582-10-11 05:06:07.123456'),
('1582-10-20', '1582-10-21 05:06:07.123456');
Retrieving values using a SELECT statement works perfectly:
SELECT * FROM dates;
date | datetime
---------------+-------------------------------
1582-10-10 | 1582-10-11 05:06:07.123456
1582-10-20 | 1582-10-21 05:06:07.123456
Retrieving them from Java using the following code does not:
var conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/db?user=postgres");
var stmt = conn.createStatement().executeQuery("SELECT * FROM dates");
while (stmt.next()) {
System.out.println(stmt.getDate(1).toString() + " | " + stmt.getTimestamp(2).toString());
}
As you can see from the output below, both rows are undistinguishable from each other, even though they are different in the database:
1582-10-20 | 1582-10-21 05:06:07.123456
1582-10-20 | 1582-10-21 05:06:07.123456
Question
What can I do to retrieve dates and timestamps as stored in the database? I tried the following:
- Using
getObject
and hoping the JDBC driver will return aLocalDate
or aLocalDateTime
. Unfortunately, the JDBC driver still returns aDate
andDateTime
, so this does not solve the problem. - Using
getString
and re-parsing the output as aLocalDate
orLocalDateTime
. This does work, but feels like a hack and I am left wondering about the robustness of the approach.