What's the correct way to convert between java.sql.Date
and LocalDate
(in both directions) in Java 8 (or higher)?
Asked
Active
Viewed 1.1e+01k times
77

maja
- 17,250
- 17
- 82
- 125
-
6The wording on the question itself is good for those also/specifically looking for conversion from java.sql.Date to java.time.LocalDate, even if the other question has a similar answer. – nikodaemus Jun 08 '16 at 20:43
-
Tip: Avoid converting *to* `java.sql.Date`. That terribly flawed class is now legacy, supplanted years ago by the modern *java.time* classes defined in JSR 310. Focus on using only the *java.time* classes. As of JDBC 4.2 and later, support for the `LocalDate` class is required in all JDBC drivers. – Basil Bourque Nov 27 '22 at 01:25
1 Answers
159
The Java 8 version (and later) of java.sql.Date
has built in support for LocalDate
, including toLocalDate
and valueOf(LocalDate)
.
To convert from LocalDate
to java.sql.Date
you can use
java.sql.Date.valueOf( localDate );
And to convert from java.sql.Date
to LocalDate
:
sqlDate.toLocalDate();
Time zones:
The LocalDate
type stores no time zone information, while java.sql.Date
does. Therefore, when using the above conversions, the results depend on the system's default timezone (as pointed out in the comments).
If you don't want to rely on the default timezone, you can use the following conversion:
Date now = new Date();
LocalDate current = now.toInstant()
.atZone(ZoneId.systemDefault()) // Specify the correct timezone
.toLocalDate();

maja
- 17,250
- 17
- 82
- 125
-
6Note that this uses the system default time zone to interpret the date, which may or may not be what you want. Often it's preferrable to specify the time zone explicitly! – marc82ch Jun 10 '16 at 07:15
-
@marc82ch A [`LocalDate`](https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html) explicitly doesn't have a time zone. Can you add some details of how you would specify one and how that would affect things? – beldaz Sep 07 '16 at 20:26
-
@beldaz I may be wrong, I don't know the internals really, but I think a java.sql.Date is represented by a long timestamp since the epoch (UTC). So, when reading from the DB DATE field, it needs to be interpreted (by the driver) in order to represent it as a long. Remember that java.sql.Date inherits from java.util.Date. So it's basically an Instant in Java 8 terms and converting it to a LocalDate needs a time zone. But I reckon that as long as the JDBC driver and your code use the same default time zone, it doesn't matter. – marc82ch Sep 11 '16 at 11:46
-
2@marc82ch You are correct. [The default time zone affects the conversion, as proved by this question](https://stackoverflow.com/questions/37779418/how-to-map-sql-date-to-localdate). you can use the yyyy-mm-dd format while converting: `java.time.LocalDate.parse(sqlDate.toString())` @maja, Can you update your answer accordingly? – Josiah Yoder Aug 17 '17 at 16:16
-
7Alternative is incorrect as java.sql.Date.toInstant() throws a UnsupportedOperationException (in Java 8) – TheCodeKiller May 16 '18 at 12:13
-
4UnsupportedOperationException is throws in java.util.Date, not in java.sql.Date, for avoid this exception use a if (sqlDate instanceof java.sql.Date) before the sqlDate.toLocalDate(), if the date is java.util.Date use sqlDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); – Ednilson Campos Jun 19 '18 at 12:30
-
I also got UnsupportedOperationException. For me this worked -> Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDate() – Shubham Pandey Mar 06 '19 at 12:09
-
3somehow there is an unwanted timezone conversion going on for me in those java.sql.Date methods - I put in a LocalDate for today, and in the database end up with a date value for yesterday – codeling Mar 07 '19 at 07:29
-
@codeling When writing to the DB, use the method `statement.setDate(2, Date.valueOf(record.date), cal);` with 'cal' being an instance of Calendar (Calendar.getInstance()). This way the driver will have the proper context. If you do not use the default system timezone, get a calendar for that zone and pass it in. – JayC667 Sep 22 '20 at 12:58
-
-
@codeling That is one of many reasons to **never use the legacy date-time classes**. They are flawed by terrible design decisions made by people who did not understand date-time handling. Use only *java.time* classes. – Basil Bourque Nov 27 '22 at 01:27