tl;dr
( (GregorianCalendar) customerSearch.get( "DateOfBirth" ) ) // Retrieve and cast object of legacy class `GregorianCalendar`.
.toZonedDateTime() // Convert from terrible legacy class to modern *java.time* class.
.toLocalDate() // Extract the date-only portion, omitting time-of-day and time zone.
java.time
You are using, and possibly abusing, terrible date-time classes that were supplanted years ago by the java.time classes defined by JSR 310.
ZonedDateTime
replaces GregorianCalendar
Instant
replaces java.util.Date
LocalDate
replaces java.sql.Date
If you must interoperate with old code not yet updated to java.time, you can convert back-and-forth. Call new conversion methods added to the old classes.
GregorianCalendar gc = customerSearch… ;
ZonedDateTime zdt = gt.toZonedDateTime() ;
If you want just the date without the time-of-day and without the time zone, extract a LocalDate
.
LocalDate dateOfBirth = zdt.toLocalDate() ;
If by Date
you meant, java.sql.Date
class, the above line should be used instead making use of LocalDate
.
If by Date
you meant java.util.Date
, that would be the wrong class to use there. That class represents a moment in UTC. By adjusting from the zoned moment in GregorianCalendar
/ZonedDateTime
to UTC, you could be changing the date.
Converting
If you need a java.util.Date
object to interoperate with old code not yet updated for java.time, you can convert. A java.util.Date
represents a moment in UTC, so we need the equivalent in java.time, Instant
, also a moment in UTC but with a finer resolution of nanoseconds rather than milliseconds.
We can extract an Instant
from our ZonedDateTime
seen above. Effectively, this is simply adjusting from a zoned value to a UTC value. Same moment, same point on the timeline, different wall-clock time.
Instant instant = zdt.toInstant() ; // Extract a `Instant`, adjusting from zone to UTC.
Use new conversion methods on the old class.
java.util.Date myJavaUtilDate = java.util.Date.from( instant ) ; // Beware of possible data-loss in the fractional second, truncating from nanos to millis.
If you need go the other direction, from legacy to modern.
Instant instant = myJavaUtilDate.toInstant() ;
Use appropriate types
If you are trying to represent a date-of-birth is is commonly done, with just a date without time-of-day and without zone, then use LocalDate
in your map. The classes GregorianCalendar
, java.util.Date
, and ZonedDateTime
all represent a moment, a specific point on the timeline. They should never be used for a date-only.
The java.sql.Date
class pretends to be a date-only, but through a terrible design decision as a subclass of java.util.Date
actually does indeed carry a time-of-day and offset/zone. This class, as noted above, has been replaced with LocalDate
.
normal Date object
There is nothing more “normal” about either java.util.Date
or java.sql.Date
than any other date-time class.
java.util.Date
represents a moment in UTC, always UTC, despite what its terribly designed toString
method tells you (a lie). Use java.time.Instant
instead when you need a moment in UTC.
java.sql.Date
is meant to represent a date-only, but as discussed, actually carries internally a time and zone/offset. Use java.time.LocalDate
instead to represent a date rather than a moment.
GregorianCalendar
represents a moment as seen in the wall-clock time used by the people of a specific region (a time zone). Instead use ZonedDateTime
for this purpose.
java.sql.Timestamp
represents a moment in UTC but with a finer resolution of nanoseconds rather than milliseconds. All the moment-related classes in java.time use a resolution of nanoseconds. So for a moment in UTC with a resolution of UTC, use java.time.Instant
instead of Timestamp
.
As of JDBC 4.2, we can directly exchange java.time classes with a database. So no need to ever touch java.sql.Date
or java.sql.Timestamp
again for your database work.
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
.
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.