How to Convert from Date to LocalDate in Java


How can we convert from Date (java.util.Date, java.sql.Date) to LocalDate (java.time.LocalDate) in Java?

Difference between Date and LocalDate

Date refers to a single instant, or moment, of time.

The value stored in a Date object is the epoch, or the number of milliseconds since January 1, 1970, 00:00:00 GMT.

Unfortunately, Date does not store information regarding time zones. When printed, the Date object makes use of Java’s default time zone.

On the other hand, LocalDate requires information about both the time, which Date has, and the time zone, which we need to specify manually.

1. Convert from java.util.Date to LocalDate

To start, we can convert from java.util.Date to Instant, which will allow us to specify a time zone using Instant::atZone.

Instant::atZone will return a ZonedDateTime, which stores information about both datetime and time zone (very easy to convert to LocalDate).

LocalDate convertToLocalDate(Date date) {
  Instant instant = date.toInstant();
  ZonedDateTime zdt = instant.atZone(ZoneId.systemDefault());
  return zdt.toLocalDate();
}

In these examples, we’re manually specifying the default time zone ZoneId::systemDefault, but we should use the time zone that best fits the context of the running application.

In Java 8, we can convert from Date to LocalDate in a single statement like so:

LocalDate convertToLocalDate(Date date) {
  return date.toInstant()
             .atZone(ZoneId.systemDefault())
             .toLocalDate();
}

We can also convert from Date to LocalDate using Java 9.

LocalDate convertToLocalDate(Date date) {
  return LocalDate.ofInstant(
           date.toInstant(), 
           ZoneId.systemDefault()
         );
}

2. Convert from java.sql.Date to LocalDate

If we want to convert an instance of java.sql.Date to LocalDate, we won’t be able to use Instant::toInstant.

In this case, we can use Instant::ofEpochMilli to convert the Date to an Instant.

This conversion would look something like this in Java 8:

LocalDate convertToLocalDate(Date date) {
  return Instant.ofEpochMilli(date.getTime())
                .atZone(ZoneId.systemDefault())
                .toLocalDate();
}

In Java 9, we would replace the Date to Instant conversion.

LocalDate convertToLocalDate(Date date) {
  return LocalDate.ofInstant(
           Instant.ofEpochMilli(date.getTime()), 
           ZoneId.systemDefault()
         );
}