diff --git a/src/main/java/org/duckdb/DuckDBResultSet.java b/src/main/java/org/duckdb/DuckDBResultSet.java index e4a5c849..9116a169 100644 --- a/src/main/java/org/duckdb/DuckDBResultSet.java +++ b/src/main/java/org/duckdb/DuckDBResultSet.java @@ -1364,7 +1364,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 e522452e..f16536b3 100644 --- a/src/main/java/org/duckdb/DuckDBVector.java +++ b/src/main/java/org/duckdb/DuckDBVector.java @@ -639,11 +639,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); } @@ -655,7 +668,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 3238472e..98bdaebe 100644 --- a/src/test/java/org/duckdb/TestTimestamp.java +++ b/src/test/java/org/duckdb/TestTimestamp.java @@ -602,4 +602,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()); + } + } }