diff --git a/presto-jdbc/src/main/java/io/prestosql/jdbc/PrestoResultSet.java b/presto-jdbc/src/main/java/io/prestosql/jdbc/PrestoResultSet.java index cc874c41a4e7..5387896b07d8 100644 --- a/presto-jdbc/src/main/java/io/prestosql/jdbc/PrestoResultSet.java +++ b/presto-jdbc/src/main/java/io/prestosql/jdbc/PrestoResultSet.java @@ -52,8 +52,10 @@ import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; +import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; +import java.time.ZoneOffset; import java.util.Calendar; import java.util.HashMap; import java.util.Iterator; @@ -296,7 +298,10 @@ private Date getDate(int columnIndex, DateTimeZone localTimeZone) } try { - return new Date(DATE_FORMATTER.withZone(localTimeZone).parseMillis(String.valueOf(value))); + long millis = DATE_FORMATTER.withZone(localTimeZone).parseMillis(String.valueOf(value)); + return Date.valueOf(Instant.ofEpochMilli(millis) + .atZone(ZoneOffset.UTC) + .toLocalDate()); } catch (IllegalArgumentException e) { throw new SQLException("Invalid date from server: " + value, e); diff --git a/presto-jdbc/src/test/java/io/prestosql/jdbc/TestJdbcResultSet.java b/presto-jdbc/src/test/java/io/prestosql/jdbc/TestJdbcResultSet.java index 14f49fcab850..4cc67f903ac9 100644 --- a/presto-jdbc/src/test/java/io/prestosql/jdbc/TestJdbcResultSet.java +++ b/presto-jdbc/src/test/java/io/prestosql/jdbc/TestJdbcResultSet.java @@ -127,6 +127,18 @@ public void testObjectTypes() assertThrows(IllegalArgumentException.class, () -> rs.getTimestamp(column)); }); + // distant past, but apparently not an uncommon value in practice; on this date Julian and Gregorian calendars should be in sync, but they appear not to be + checkRepresentation("DATE '0001-01-01'", Types.DATE, (rs, column) -> { + assertEquals(rs.getObject(column), Date.valueOf(LocalDate.of(1, 1, 1))); + assertEquals(rs.getDate(column), Date.valueOf(LocalDate.of(1, 1, 1))); + }); + + // distant past, before Julian-Gregorian calendar "default cut-over", but after 0001-01-01 when Julian and Gregorian calendars are supposed to be in sync + checkRepresentation("DATE '1300-01-01'", Types.DATE, (rs, column) -> { + assertEquals(rs.getObject(column), Date.valueOf(LocalDate.of(1300, 1, 1))); + assertEquals(rs.getDate(column), Date.valueOf(LocalDate.of(1300, 1, 1))); + }); + checkRepresentation("TIME '09:39:05'", Types.TIME, (rs, column) -> { assertEquals(rs.getObject(column), Time.valueOf(LocalTime.of(9, 39, 5))); assertThrows(() -> rs.getDate(column));