The implementation of java.sql.Date (imho) is really not perfect.
In order to convert java.util.Date to LocalDate the web is full of code blocks like this:
dateToConvert.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate();
- above code works perfect for java.util.Date because of the way it implements toInstant(). (As expected " return Instant.ofEpochMilli(getTime())")
- As java.sql.Date is a subclass of java.util.Date code operating on the Date object might now know it operates on a java.sql.Date. (Hey - that's one aspect of object orientation, right??). So if it gets java.util.Date code works well, if it gets java.sql.Date it fails.
- Code could now explicitly check for the Date type, and then (if it operates on java.sql.Date) it could do a downcast to java.sql.Date and use the toLocalDate() method. Needless to say, that this is ugly.
As developer I'd like to have one method working properly - toLocalDate (internally using deprectated methods) only exists for java.sql.Date so cannot be used on java.util.Date, and toInstant fails on java.sql.Date.
I changed my "Date to LocalDate" conversion code to this:
public static LocalDate asLocalDate(java.util.Date date) {
return date == null ? null : LocalDate.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());
}
This works independent of the date type passed in. Basically it means "dont call java.util.Date.toInstant() as you might get a java.sql.Date, which then breaks your code.
I really don't understand why they implement such traps on purpose within the JDK.