diff --git a/src/main/java/org/duckdb/DuckDBResultSet.java b/src/main/java/org/duckdb/DuckDBResultSet.java index 0d14712d..70e7d19e 100644 --- a/src/main/java/org/duckdb/DuckDBResultSet.java +++ b/src/main/java/org/duckdb/DuckDBResultSet.java @@ -1356,7 +1356,7 @@ public T getObject(int columnIndex, Class type) throws SQLException { ", SQL type: " + sqlType); } } else if (type == LocalDateTime.class) { - if (isTimestamp(sqlType)) { + if (isTimestamp(sqlType) || sqlType == DuckDBColumnType.DATE) { return type.cast(getLocalDateTime(columnIndex)); } else { throw new SQLException("Can't convert value to LocalDateTime, Java type: " + type + diff --git a/src/main/java/org/duckdb/DuckDBVector.java b/src/main/java/org/duckdb/DuckDBVector.java index 7e4b923b..8c1b958f 100644 --- a/src/main/java/org/duckdb/DuckDBVector.java +++ b/src/main/java/org/duckdb/DuckDBVector.java @@ -632,11 +632,24 @@ private boolean isType(DuckDBColumnType columnType) { return duckdb_type == columnType; } + private LocalDateTime getLocalDateTimeFromDate(int idx) throws SQLException { + LocalDate ld = getLocalDate(idx); + if (ld == null) { + return null; + } + return ld.atStartOfDay(); + } + Timestamp getTimestamp(int idx, Calendar calNullable) throws SQLException { if (check_and_null(idx)) { return null; } - LocalDateTime ldt = getLocalDateTimeFromTimestamp(idx, calNullable); + final LocalDateTime ldt; + if (duckdb_type == DuckDBColumnType.DATE) { + ldt = getLocalDateTimeFromDate(idx); + } else { + ldt = getLocalDateTimeFromTimestamp(idx, calNullable); + } if (ldt != null) { return Timestamp.valueOf(ldt); } @@ -648,7 +661,12 @@ Timestamp getTimestamp(int idx, Calendar calNullable) throws SQLException { } LocalDateTime getLocalDateTime(int idx) throws SQLException { - LocalDateTime ldt = getLocalDateTimeFromTimestamp(idx, null); + final LocalDateTime ldt; + if (duckdb_type == DuckDBColumnType.DATE) { + ldt = getLocalDateTimeFromDate(idx); + } else { + ldt = getLocalDateTimeFromTimestamp(idx, null); + } if (ldt != null) { return ldt; } diff --git a/src/test/java/org/duckdb/TestTimestamp.java b/src/test/java/org/duckdb/TestTimestamp.java index a433ab0b..59e798c2 100644 --- a/src/test/java/org/duckdb/TestTimestamp.java +++ b/src/test/java/org/duckdb/TestTimestamp.java @@ -581,4 +581,36 @@ public static void test_timestamp_before_epoch() throws Exception { TimeZone.setDefault(defaultTimeZone); } } + + public static void test_timestamp_read_ts_from_date() throws Exception { + try (Connection conn = DriverManager.getConnection(JDBC_URL); Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT '2020-01-02'::DATE")) { + assertTrue(rs.next()); + assertEquals(rs.getTimestamp(1).toLocalDateTime().toLocalDate(), LocalDate.of(2020, 1, 2)); + assertFalse(rs.next()); + } + try (Connection conn = DriverManager.getConnection(JDBC_URL); Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT NULL::DATE")) { + assertTrue(rs.next()); + assertNull(rs.getTimestamp(1)); + assertTrue(rs.wasNull()); + assertFalse(rs.next()); + } + } + + public static void test_timestamp_read_ldt_from_date() throws Exception { + try (Connection conn = DriverManager.getConnection(JDBC_URL); Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT '2020-01-02'::DATE")) { + assertTrue(rs.next()); + assertEquals(rs.getObject(1, LocalDateTime.class).toLocalDate(), LocalDate.of(2020, 1, 2)); + assertFalse(rs.next()); + } + try (Connection conn = DriverManager.getConnection(JDBC_URL); Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT NULL::DATE")) { + assertTrue(rs.next()); + assertNull(rs.getObject(1, LocalDateTime.class)); + assertTrue(rs.wasNull()); + assertFalse(rs.next()); + } + } }