Java8 java.util.Date conversion to java.time.ZonedDateTime

JavaDateDatetimeJava 8Java Time

Java Problem Overview


I am getting the following exception while trying to convert java.util.Date to java.time.LocalDate.

java.time.DateTimeException: Unable to obtain ZonedDateTime from TemporalAccessor: 2014-08-19T05:28:16.768Z of type java.time.Instant

The code is as follow:

public static Date getNearestQuarterStartDate(Date calculateFromDate){
	
	int[] quaterStartMonths={1,4,7,10};		
	Date startDate=null;
	
	ZonedDateTime d=ZonedDateTime.from(calculateFromDate.toInstant());
	int frmDateMonth=d.getMonth().getValue();

Is there something wrong in the way I am using the ZonedDateTime class?

As per documentation, this should convert a java.util.Date object to ZonedDateTime. The date format above is standard Date?

Do I have to fallback on Joda time?

If someone could provide some suggestion, it would be great.

Java Solutions


Solution 1 - Java

To transform an Instant to a ZonedDateTime, ZonedDateTime offers the method ZonedDateTime.ofInstant(Instant, ZoneId). So

So, assuming you want a ZonedDateTime in the default timezone, your code should be

ZonedDateTime d = ZonedDateTime.ofInstant(calculateFromDate.toInstant(),
                                          ZoneId.systemDefault());

Solution 2 - Java

To obtain a ZonedDateTime from a Date you can use:

calculateFromDate.toInstant().atZone(ZoneId.systemDefault())

You can then call the toLocalDate method if you need a LocalDate. See also: https://stackoverflow.com/questions/21242110/convert-java-util-date-to-java-time-localdate/21242111

Solution 3 - Java

The Answer by assylias and the Answer by JB Nizet are both correct:

  1. Call the new conversion method added to the legacy class, java.util.Date::toInstant.
  2. Call Instant::atZone, passing a ZoneId, resulting in a ZonedDateTime.

enter image description here

But your code example is aimed at quarters. For that, read on.

Quarters

No need to roll-your-own handling of quarters. Use a class already written and tested.

org.threeten.extra.YearQuarter

The java.time classes are extended by the ThreeTen-Extra project. Among the many handy classes provided in that library you will find Quarter and YearQuarter.

First get your ZonedDateTime.

ZonedId z = ZoneID.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = myJavaUtilDate.toInstant().atZone( z ) ;

Determine the year-quarter for that particular date.

YearQuarter yq = YearQuarter.from( zdt ) ;

Next we need the start date of that quarter.

LocalDate quarterStart = yq.atDay( 1 ) ;

While I do not necessarily recommend doing so, you could use a single line of code rather than implement a method.

LocalDate quarterStart =                    // Represent a date-only, without time-of-day and without time zone.
    YearQuarter                             // Represent a specific quarter using the ThreeTen-Extra class `org.threeten.extra.YearQuarter`. 
    .from(                                  // Given a moment, determine its year-quarter.
        myJavaUtilDate                      // Terrible legacy class `java.util.Date` represents a moment in UTC as a count of milliseconds since the epoch of 1970-01-01T00:00:00Z. Avoid using this class if at all possible.
        .toInstant()                        // New method on old class to convert from legacy to modern. `Instant` represents a moment in UTC as a count of nanoseconds since the epoch of 1970-01-01T00:00:00Z. 
        .atZone(                            // Adjust from UTC to the wall-clock time used by the people of a particular region (a time zone). Same moment, same point on the timeline, different wall-clock time.
            ZoneID.of( "Africa/Tunis" )     // Specify a time zone using proper `Continent/Region` format. Never use 2-4 letter pseudo-zone such as `PST` or `EST` or `IST`. 
        )                                   // Returns a `ZonedDateTime` object.
    )                                       // Returns a `YearQuarter` object.
    .atDay( 1 )                             // Returns a `LocalDate` object, the first day of the quarter. 
;

By the way, if you can phase out your use of java.util.Date altogether, do so. It is a terrible class, along with its siblings such as Calendar. Use Date only where you must, when you are interfacing with old code not yet updated to java.time.


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.

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.

Solution 4 - Java

The answer didn't work for me on Java 10 storing util.Date in UTC.

Date.toInstant() seems to convert the EpochMillis into the local time zone of the server.

ZDT.ofInstant(instant, zoneId) and instant.atZone(zoneId) seem to just tag on a TZ on the instant, but it's already messed up with.

I couldn't find a way to prevent Date.toInstant() from messing with the UTC time with the system time zone.

The only way I found to work around this was to go through the sql.Timestamp class:

new java.sql.Timestamp(date.getTime()).toLocalDateTime()
                                      .atZone(ZoneId.of("UTC"))
                                      .withZoneSameInstant(desiredTZ)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionIronlucaView Question on Stackoverflow
Solution 1 - JavaJB NizetView Answer on Stackoverflow
Solution 2 - JavaassyliasView Answer on Stackoverflow
Solution 3 - JavaBasil BourqueView Answer on Stackoverflow
Solution 4 - JavaTheArchitectView Answer on Stackoverflow