-1

This should be quite simple

customerSearch.get("DateOfBirth") where customerSearch is a HashMap<String, Object> and it's a Gregorian Date.

But I need a normal Date object.

I tried

Date dateOfBirth = new Date(
        ((GregorianCalendar) customerSearch.get("DateOfBirth")).getTimeInMillis());

but said Gregorian Date cannot be cast to Date.

Any help?

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
user10867569
  • 157
  • 2
  • 6
  • 3
    Possible duplicate of [convert XMLGregorianCalendar to date i.e "MM/DD/YYYY hh:mm:ss AM"](https://stackoverflow.com/questions/16706431/convert-xmlgregoriancalendar-to-date-i-e-mm-dd-yyyy-hhmmss-am) – Eray Balkanli Jan 28 '19 at 14:58
  • Why are you fighting with `GregorianCalendar` and `Date`? Those classes are poorly designed and long outdated. No one should use them in 2019 IMHO. Instead use `LocalDate` from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Jan 28 '19 at 15:10
  • I cannot reproduce. Your code runs nicely on my Java 8 and in one run produced a `Date` of `Wed Dec 29 00:00:00 UTC 1999`. [How to create a Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve), please. – Ole V.V. Jan 28 '19 at 15:15
  • @ErayBalkanli That question is about `XMLGregorianCalendar`, this one seems to be about `GregorianCalendar` (or else I don’t know, but hardly `XMLGregorianCalendar`). So not a duplicate of that one, possibly of other questions. – Ole V.V. Jan 28 '19 at 15:20
  • Are you getting the error message on compile time or on runtime? Would you care to quote the error message *verbatim* (paste it into the question)? Thx in advance. – Ole V.V. Jan 28 '19 at 15:34
  • FYI, the terribly troublesome old date-time classes such as [`java.util.Date`](https://docs.oracle.com/javase/10/docs/api/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/javase/10/docs/api/java/util/Calendar.html), and `java.text.SimpleDateFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [*java.time*](https://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) classes built into Java 8 and later. See [*Tutorial* by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque Feb 06 '19 at 06:44

2 Answers2

2

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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
0

There is no java class GregorianDate. Unless it is your own class which if so you didn't mention. So, just in case is Gregorian Date just a regular Date as most of the world today uses Gregorian calendar? So instances of what class does your map holds in your HashMap<String, Object>? If it is just a regular Date then your code should be just:

Date dateOfBirth = (Date)(customerSearch.get("DateOfBirth"));
Michael Gantman
  • 7,315
  • 2
  • 19
  • 36