Reputation: 2452
I have a need to convert from a LocalDateTime with both a date and time component to a Date without losing the time part. I have been doing something like:
LocalDateTime ldt = //some full date-time value
Date date = java.util.Date.valueOf(ldt.toLocalDate());
, but am obviously losing the time part..I see there is also a LocalDateTime.toLocalTime(), however I need both date and time together.
Thank you
Upvotes: 1
Views: 1353
Reputation: 338171
Apparently, you inadvertently used the class java.sql.Date
where you thought you were using java.util.Date
. But that issue is moot: use java.time classes instead of those terrible old date-time classes.
myPreparedStatement.setObject( … , myLocalDateTime ) ;
…and…
myResultSet.getObject( … , LocalDateTime.class )
Apparently you are inadvertently using java.sql.Date
which pretends to have no time of day. Unfortunately, it’s terrible class design inherits from java.util.Date
which does have a time-of-day. So the sql
sets its time to 00:00:00. And the documentation tells us to ignore the fact of their inheritance. Terrible design, terrible names, terrible classes all around.
For all these reasons and more, these old classes were supplanted years ago by the java.time classes.
As of JDBC 4.2, we can exchange java.time classes with the database. No need to ever touch java.util.Date
, java.sql.Date
, java.sql.Timestamp
again.
A LocalDateTime
should be stored in a database column of a type akin to the SQL-standard type TIMESTAMP WITHOUT TIME ZONE
. These type intentionally lack any concept of time zone or offset-from-UTC. As such, these types cannot represent a moment, cannot hold a specific point on the timeline. These are likely not what you want in most business scenarios.
myPreparedStatement.setObject( … , myLocalDateTime ) ;
Retrieval:
myLocalDateTime = myResultSet.getObject( … , LocalDateTime.class ) ;
If they cannot represent a moment, what good are these types? In what scenarios is the use of java.time.LocalDateTime
class & TIMESTAMP WITHOUT TIME ZONE
column appropriate? These three:
LocalDateTime
. To print a report or display a calendar, dynamically apply a time zone (ZoneId
) to generate a specific moment (ZonedDateTime
or Instant
). This must be done on-the-fly rather than storing the value.In contrast, to store a moment, use a database column of a type akin to the SQL-standard type TIMESTAMP WITH TIME ZONE
. For such a column, in Java use Instant
class. This class represents a moment in UTC with a resolution of nanoseconds.
myPreparedStatement.setObject( … , myInstant ) ;
Retrieval:
myInstant = myResultSet.getObject( … , Instant.class ) ;
If you are certain your LocalDateTime
was meant implicitly to represent a moment in the wall-clock time used by the people of a particular region (a time zone), apply a ZoneId
to get a ZonedDateTime
.
Specify a proper time zone name in the format of continent/region
, such as America/Montreal
, Africa/Casablanca
, or Pacific/Auckland
. Never use the 3-4 letter abbreviation such as EST
or IST
as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdt = myLocalDateTime.atZone( z ) ;
Then extract a Instant
object to adjust into UTC.
Instant instant = zdt.toInstant();
Store in database.
myPreparedStatement.setObject( … , instant ) ;
Retrieve from database.
Instant instant = myResultSet.getObject( … , Instant.class ) ;
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
.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
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.
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.
Upvotes: 0
Reputation: 7792
java.util.Date
does hold time component if you provide it. But in the first place why would you want to work with old Date rather then keep with the new java 8 java.time
package? In any case to answer your question I suggest to retrieve epoch milliseconds and then create your Date
from that. So It would look something like this:
long epoch = ZonedDateTime.of(ldt, ZoneId.systemDefault()).toInstant().toEpochMilli();
Date date = new Date(epoch);
Due to request from Basil Bourque - an explanation why ZonedDateTime
is needed: in order to extract epoch - number of milliseconds from "1.1.1970 00:00:00+0000" you will need to convert LocalDateTime
(which is not absolute time and could mean a different instant in time in different locations) to ZonedDateTime
that also holds a location and thus is absolute time. Thus from ZonedDateTime
you can extract the epoch.
Upvotes: 0
Reputation: 208
That is because java.sql.Date
doesn't include the time.
You could use the class java.sql.Timestamp
instead, which includes both date and time.
Upvotes: 4