Hello! This is meant as a comment on JDK-8249280 (Date and Timestamp valueOf wrong for BCE years) and/or JDK-8272194 (java.sql.Date::toLocalDate() broken for dates before 1 A.D.) as I can't comment directly.
The direct consequence of the bug is that using big negative timestamps it's possible to construct invalid java.sql.Date or java.sql.Timestamp instances that throw when toLocalDate() or toLocalDateTime() is called on them. The following code: ``` var millis = -9223371997689600000L; var timestamp = new Timestamp(millis); var localDateTime = timestamp.toLocalDateTime(); // throws ``` throws ``` Exception in thread "main" java.time.DateTimeException: Invalid date 'February 29' as '292269053' is not a leap year at java.base/java.time.LocalDate.create(LocalDate.java:459) at java.base/java.time.LocalDate.of(LocalDate.java:273) at java.base/java.time.LocalDateTime.of(LocalDateTime.java:363) at java.sql/java.sql.Timestamp.toLocalDateTime(Timestamp.java:519) at [...] ``` Obviously `new java.sql.Date(millis).toLocalDate()` fails the same way, and this happens for all timestamps for a day every 4 years, so fairly often. This makes the bug much worse than implied by their descriptions as it's unintuitive to assume that `new Timestamp(any).toLocalDateTime()` could ever throw. All the values are naively valid and possible. Is it a good time to reevaluate the bugs' priority? Returning a bad value is one thing, throwing is another. The workaround is clear - just use Instant instead: ``` var instant = Instant.ofEpochMilli(millis); var localDateTime = LocalDateTime.ofInstant(instant, utcOrDefaultZone); ``` I'm sure this never happens, but perhaps the old-timey Date/Timestamp should be reimplemented using the new java.time types? Thank you, Petr Janeček