-5

Time information is missing when converting LocalDate to java.util.Date

My input date is in the format "2019-08-30T19:47:22+00:00" (String). I have to convert it to java.util.Data. I would like to do it using java 8.

String input = "2019-08-30T19:47:22+00:00";
Date date = null;
LocalDate dateTime = LocalDate.parse(input, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
date = Date.from(dateTime.atStartOfDay(ZoneId.systemDefault()).toInstant());
System.out.println("Parsed from LoacalDate: " + date);
System.out.println("From new Date(): " + new Date());

Output

  • Parsed from LoacalDate: Fri Aug 30 00:00:00 CDT 2019 From new
  • Date(): Fri Aug 30 17:16:23 CDT 2019

In the output time information is missing. How to get time information?

Thiagarajan Ramanathan
  • 1,035
  • 5
  • 24
  • 32
  • 4
    `LocalDate` doesn't have a time. Look at `LocalDateTime` or `ZonedDateTime` or `OffsetDateTime` if you need time. But I'm curious what you thought `dateTime.atStartOfDay()` does. – shmosel Aug 30 '19 at 22:25
  • 2
    What does the javadoc of LocalDate say about that class? What does it represent? – JB Nizet Aug 30 '19 at 22:25
  • 1
    Side question: Why do you have to convert it to `java.util.Date`? `java.time` has been out for 5 years now - are you working with an older API? A lot of stuff has managed to switch over, especially ORMs. – Clockwork-Muse Aug 30 '19 at 22:32
  • 1
    @Clockwork-Muse I am using a library. It expects the date in java.util.Date – Thiagarajan Ramanathan Aug 30 '19 at 23:03

2 Answers2

2

tl;dr

LocalDate stores only a date, so wrong class to use.

java.util.Date                              // Terrible class, now legacy. Avoid. Replaced by `java.time.Instant` in JSR 310. Use only where required, to interoperate with old code not yet updated for java.time.
.from(                                      // Convert from modern `Instant` to legacy `Date`.
    OffsetDateTime                          // The modern class to represent a moment in the context of an offset-from-UTC (a number of hours-minutes-seconds). Not to be confused with a time zone, which is a history of changes to the offset used by the people of a particular region. 
    .parse( "2019-08-30T19:47:22+00:00" )   // Parse text into an `OffsetDateTime` object.
    .toInstant()                            // Extract an `Instant`, a more basic building-block class that represent a moment in UTC (an offset of zero). 
)
.toString()                                 // Generates text representing the value of the `Date`. But this method lies! It dynamically applies your JVM’s current default time zone while generating the text.

Note that java.util.Date::toString tells a lie! That method dynamically applies the JVM’s current default time zone while generating the text to represent the value that is actually in UTC. One of many reasons to never use this Date class.

Details

You are using the wrong classes.

LocalDate

LocalDate represents a date only, no time-of-day, no time zone or offset.

By parsing your input representing a moment as simply a date, you are lopping off the time-of-day and the offset-from-UTC.

OffsetDateTime

Your input "2019-08-30T19:47:22+00:00" represents a moment: a date, a time-of-day, an offset-from-UTC of zero hours-minutes-seconds. So parse that as a OffsetDateTime.

OffsetDateTime odt = OffsetDateTime.parse( "2019-08-30T19:47:22+00:00" ) ;

Avoid legacy date-time classes

The java.util.Date class is terrible, and should no longer be used. It was supplanted years ago by the modern java.time classes as of the adoption of JSR 310.

However, if you must interoperate with old code not yet updated to java.time, you can convert back-and-forth. Look to new to…/from… methods added to the old classes.

The equivalent of java.util.Date is java.time.Instant, both representing a moment in UTC (though with a difference in resolution, milliseconds versus nanoseconds). So extract a basic Instant object from our more flexible OffsetDateTime.

Instant instant = odt.toInstant() ;
java.util.Date d = Date.from( instant ) ;
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
-1

I was able to make it work using the following code snippet

  LocalDateTime dateTime = LocalDateTime.parse(input,DateTimeFormatter.ISO_OFFSET_DATE_TIME);
  date = Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
  System.out.println("Parsed from LoacalDate:" + date);
  System.out.println("From new Date():" + new Date());
Thiagarajan Ramanathan
  • 1,035
  • 5
  • 24
  • 32
  • Thiagarajan Ramanathan, you’re throwing away the offset information from the string (+00:00) and substituting the offset of the JVM’s default time zone, in most cases leading to an incorrect result. Note that you don’t want a `Date` that prints as Fri Aug 30 19:47:22, but a `Date` that represents the same moment in time as the string. – Ole V.V. Aug 31 '19 at 08:33