1

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 a LocalDate or a LocalDateTime. Unfortunately, the JDBC driver still returns a Date and DateTime, so this does not solve the problem.
  • Using getString and re-parsing the output as a LocalDate or LocalDateTime. This does work, but feels like a hack and I am left wondering about the robustness of the approach.
aochagavia
  • 5,887
  • 5
  • 34
  • 53
  • Why would you be tracking moments to the microsecond in the 1500s? That seems absurd. – Basil Bourque Feb 12 '22 at 17:01
  • You need to use `getObject(1, LocalDateTime.class)` or `getObject(1, LocalDate.class)` to obtain values of those classes, not just `getObject(1)`. – Mark Rotteveel Feb 13 '22 at 08:37
  • Thanks! @Basil Bourque: in case you are curious, I am writing a library and I don't want to make any assumptions about the user's data – aochagavia Feb 14 '22 at 08:08

0 Answers0