Set the time-of-day on a ZonedDateTime in java.time?

Basil Bourque picture Basil Bourque · Apr 28, 2016 · Viewed 13.3k times · Source

How can I alter the time-of-day portion of an existing ZonedDateTime object? I want to keep the date and time zone but alter the hour and minutes.

Answer

Basil Bourque picture Basil Bourque · Apr 28, 2016

tl;dr

zdt.with ( LocalTime.of ( 16 , 15 ) )

Immutable objects

The java.time classes use the Immutable Objects pattern to create fresh objects rather than alter (“mutate”) the original object.

with()

The ZonedDateTime::with method is a flexible way to generate a new ZonedDateTime based on another but with some particular difference. You can pass any object implementing the TemporalAdjustor interface.

In this case we want to change just the time-of-day. A LocalTime object represents a time-of-day without any date and without any time zone. And LocalTime implements the TemporalAdjustor interface. So just that time-of-day value is applied while keeping the date and the time zone as-is.

ZonedDateTime marketOpens = ZonedDateTime.of ( LocalDate.of ( 2016 , 1 , 4 ) , LocalTime.of ( 9 , 30 ) , ZoneId.of ( "America/New_York" ) );
ZonedDateTime marketCloses = marketOpens.with ( LocalTime.of ( 16 , 0 ) );

Double-check that the duration of the span of time is as expected, six and a half hours.

Duration duration = Duration.between ( marketOpens , marketCloses );

Dump to console.

System.out.println ( "marketOpens: " + marketOpens + " | marketCloses: " + marketCloses + " | duration: " + duration );

marketOpens: 2016-01-04T09:30-05:00[America/New_York] | marketCloses: 2016-01-04T16:00-05:00[America/New_York] | duration: PT6H30M

Keep in mind that in this example we are also implicitly adjusting the seconds and fractional second in the time-of-day. The LocalTime object carries with it the hour, minute, second, and fractional second. We specified an hour and a minute. Our omission of a second and fractional second resulted in a default value of 0 for both during construction of our LocalTime. All four aspects of the LocalTime were applied to get our fresh ZonedDateTime.

Quite a few classes implement the TemporalAdjustor interface. See the list on that class doc, including LocalDate, Month, Year, and more. So you can pass any of those to alter that aspect of a date-time value.

Read the comment by Hochschild. You must understand the behavior when you specify a time-of-day that is invalid for a specific date & zone. For example, during a Daylight Saving Time (DST) cut-over.