title: Missed opportunity to fix JDBC date handling in Java 8?
body: <p>Can any Java 8 + JDBC expert tell me if something's wrong in the following reasoning? And, if in the secrets of Gods, why this hasn't been done?</p>
  
  <p>A <code>java.sql.Date</code> is currently the type used by JDBC to map to the DATE SQL type, which represents a date without time, and without timezone. But this class is awfully designed, since it's in fact a subclass of <code>java.util.Date</code>, which stores a precise instant in time, up to the millisecond.</p>
  
  <p>To represent the date 2015-09-13 in database, we're thus forced to choose a timezone, parse the string "2015-09-13T00:00:00.000" in that timezone as a java.util.Date to get a millisecond value, then construct a <code>java.sql.Date</code> from this millisecond value, and finally call <code>setDate()</code> on the prepared statement, passing a Calendar holding the timezone chosen in order for the JDBC driver to be able to correctly recompute the date 2015-09-13 from this millisecond value. This process is made a bit simpler by using the default timezone everywhere, and not passing a Calendar.</p>
  
  <p>Java 8 introduces a LocalDate class, which is a much better fit for the DATE database type, since it's not a precise moment in time, and is thus not dependent on the timezone. And Java 8 also introduces default methods, which would allow to make backward-compatible changes to the PreparedStatement and ResultSet interfaces.</p>
  
  <p>So, haven't we missed a huge opportunity to clean up the mess in JDBC while still maintaining backward compatibility? Java 8 could simply have added those default methods to PreparedStatement and ResultSet:</p>
  
  <pre><code>default public void setLocalDate(int parameterIndex, LocalDate localDate) {
      if (localDate == null) {
          setDate(parameterIndex, null);
      }
      else {
          ZoneId utc = ZoneId.of("UTC");
          java.util.Date utilDate = java.util.Date.from(localDate.atStartOfDay(utc).toInstant());
          Date sqlDate = new Date(utilDate.getTime());
          setDate(parameterIndex, sqlDate, Calendar.getInstance(TimeZone.getTimeZone(utc)));
      }
  }
  
  default LocalDate getLocalDate(int parameterIndex) {
      ZoneId utc = ZoneId.of("UTC");
      Date sqlDate = getDate(parameterIndex, Calendar.getInstance(TimeZone.getTimeZone(utc)));
      if (sqlDate == null) {
          return null;
      }
  
      java.util.Date utilDate = new java.util.Date(sqlDate.getTime());
      return utilDate.toInstant().atZone(utc).toLocalDate();
  }
  </code></pre>
  
  <p>Of course, the same reasoning applies to the support of Instant for the TIMESTAMP type, and the support of LocalTime for the TIME type.</p>