tl;dr
Is there a simple way to convert a LocalDate (introduced with Java 8) to java.util.Date object? By 'simple', I mean simpler than this
Nope. You did it properly, and as concisely as possible.
java.util.Date.from( // Convert from modern java.time class to troublesome old legacy class. DO NOT DO THIS unless you must, to inter operate with old code not yet updated for java.time.
myLocalDate // `LocalDate` class represents a date-only, without time-of-day and without time zone nor offset-from-UTC.
.atStartOfDay( // Let java.time determine the first moment of the day on that date in that zone. Never assume the day starts at 00:00:00.
ZoneId.of( "America/Montreal" ) // Specify time zone using proper name in `continent/region` format, never 3-4 letter pseudo-zones such as “PST”, “CST”, “IST”.
) // Produce a `ZonedDateTime` object.
.toInstant() // Extract an `Instant` object, a moment always in UTC.
)
Read below for issues, and then think about it. How could it be simpler? If you ask me what time does a date start, how else could I respond but ask you “Where?”?. A new day dawns earlier in Paris FR than in Montréal CA, and still earlier in Kolkata IN, and even earlier in Auckland NZ, all different moments.
So in converting a date-only (LocalDate
) to a date-time we must apply a time zone (ZoneId
) to get a zoned value (ZonedDateTime
), and then move into UTC (Instant
) to match the definition of a java.util.Date
.
Details
Firstly, avoid the old legacy date-time classes such as java.util.Date
whenever possible. They are poorly designed, confusing, and troublesome. They were supplanted by the java.time classes for a reason, actually, for many reasons.
But if you must, you can convert to/from java.time types to the old. Look for new conversion methods added to the old classes.
java.util.Date
→ java.time.LocalDate
Keep in mind that a java.util.Date
is a misnomer as it represents a date plus a time-of-day, in UTC. In contrast, the LocalDate
class represents a date-only value without time-of-day and without time zone.
Going from java.util.Date
to java.time means converting to the equivalent class of java.time.Instant
. The Instant
class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Instant instant = myUtilDate.toInstant();
The LocalDate
class represents a date-only value without time-of-day and without time zone.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
So we need to move that Instant
into a time zone. We apply ZoneId
to get a ZonedDateTime
.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );
From there, ask for a date-only, a LocalDate
.
LocalDate ld = zdt.toLocalDate();
java.time.LocalDate
→ java.util.Date
To move the other direction, from a java.time.LocalDate
to a java.util.Date
means we are going from a date-only to a date-time. So we must specify a time-of-day. You probably want to go for the first moment of the day. Do not assume that is 00:00:00
. Anomalies such as Daylight Saving Time (DST) means the first moment may be another time such as 01:00:00
. Let java.time determine that value by calling atStartOfDay
on the LocalDate
.
ZonedDateTime zdt = myLocalDate.atStartOfDay( z );
Now extract an Instant
.
Instant instant = zdt.toInstant();
Convert that Instant
to java.util.Date
by calling from( Instant )
.
java.util.Date d = java.util.Date.from( instant );
More info
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date
, Calendar
, & SimpleDateFormat
.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.*
classes. Hibernate 5 & JPA 2.2 support java.time.
Where to obtain the java.time classes?
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval
, YearWeek
, YearQuarter
, and more.
java.util.Date
altogether – Fogdogjava.util.Date
by default is expected not only to represent informations about day (year/month/day), but also about time of day so we need to somehow provide this informations (here helpsatStartOfDay
). – WareroomLocalDate
is not an instant in time, it is a date, such as "30 Jan 2014". It is not tied to any particular instant until you give it a time zone. I'm not entirely sure you understand what you are asking... – PiddleDate
andInstant
are internally reckoned in UTC and (thankfully) have no notion of local time zone.LocalDate
andLocalDateTime
are intended to represent their respective temporal values in arbitrary local time zones which most of the time are not UTC. Hence there is no simple, historically consistent way to directly convert from one form to the other without knowing more information. – StagingDate
. The@Basic
annotation of JPA 2.1, for example, directly recognizesDate
andCalendar
but will only work withInstant
as a serializable type. I would say he's doing the right thing by using the new Date-Time API in his new code and usingDate
to interoperate. – StagingDate
andInstant
both include the notion of time. Interconverting betweenLocalDate
andDate
therefore means that you are necessarily dealing with a notion of time, even if you don't intend to use time information. You can't convert from "07-Sept-2015 in some local time zone" (LocalDate
) to "milliseconds since midnight 01-Jan-1970 UTC" (Date
) without knowing what "some local time zone" is. – Staging