Set hours minutes and seconds to 00 in ZonedDateTime or Instant

WitVault picture WitVault · Mar 3, 2017 · Viewed 19.1k times · Source

I have a date string in Utc format -

    String dateStr = "2017-03-03T13:14:28.666Z";

And I want to convert it to below format in Java date representation in ZonedDateTime.

When ZonedDateTime is printed it should show

    String dateStr = "2017-03-03T00:00:00.000Z";

I have tried following code -

    String timeZone = "America/Los_Angeles";
    DateTimeFormatter dtf1 = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX");
    DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    ZoneId zoneId1 = ZoneId.of(timeZone);
    String dateStr = "2017-03-03T13:14:28.666Z";
    Instant inst = Instant.parse(dateStr, dtf2);


    ZonedDateTime dateTimeInTz = ZonedDateTime.ofInstant(inst, zoneId1);

    ZonedDateTime startTime = dateTimeInTz.with(LocalTime.of(0, 0, 0, 0));
    ZonedDateTime endTime = dateTimeInTz.with(LocalTime.MAX);

    System.out.println("Start:"+startTime+", End:"+endTime);
    System.out.println("Start:"+startTime.toString()+", End:"+endTime.toString());  

    ZonedDateTime nT = ZonedDateTime.of ( LocalDate.parse(dateStr, dtf1) , LocalTime.of (0,0,0,0) , ZoneId.of ( timeZone ) );

    System.out.println("Start:"+nT);

Output:

Start:2017-03-03T00:00-08:00[America/Los_Angeles], End:2017-03-03T23:59:59.999999999-08:00[America/Los_Angeles]
Start:2017-03-03T00:00-08:00[America/Los_Angeles], End:2017-03-03T23:59:59.999999999-08:00[America/Los_Angeles]
Start:2017-03-03T00:00-08:00[America/Los_Angeles]

I want the start time to be normalized in ZonedDateTime. I want to achieve it using java libraries only not any third party library.

Answer

Basil Bourque picture Basil Bourque · Mar 3, 2017

tl;dr

You are working too hard.

Instant.parse( "2017-03-03T13:14:28.666Z" )
       .truncatedTo( ChronoUnit.DAYS )
       .toString()

2017-03-03T00:00.00Z

Details

What does "normalized in ZonedDateTime" mean? Please edit your Question to clarify.

When ZonedDateTime is printed it should show … "2017-03-03T00:00:00.000Z"

What you are asking is a contradiction. A ZonedDateTime has an assigned time zone for when you want to view a moment though the wall-clock time of a particular region. So asking for a ZonedDateTime to generate a string in UTC such as "2017-03-03T00:00:00.000Z" makes no sense. The Z is short for Zulu and means UTC.

Your input string is in standard ISO 8601 format. The java.time classes use these standard formats by default. So no need to specify a formatting pattern, no need for the DateTimeFormatter class.

Parse as an Instant, a point on the timeline in UTC with a resolution of nanoseconds.

Instant instant = Instant.parse( "2017-03-03T13:14:28.666Z" );

If you want midnight in UTC, truncate.

Instant instantMidnightUtc = instant.truncatedTo( ChronoUnit.DAYS );

instantMidnightUtc.toString(): 2017-03-03T00:00.00Z

No need for the ZonedDateTime class.

If you want to work with a date-only without any time-of-day and without a time zone, use the LocalDate class.

By the way, do not assume the first moment of the day is always 00:00:00. That is true for UTC. But various time zones may have anomalies such as Daylight Saving Time (DST) where the day may start at another time-of-day such as 01:00:00.


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.

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.