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

1

26

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.

Heliogravure answered 27/4, 2016 at 23:49 Comment(0)
H
50

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.

Heliogravure answered 27/4, 2016 at 23:49 Comment(1)
Correct examples. However, market opening and closing times are usually defined as local times, not as UTC-timestamps, so the types LocalDateTime and LocalTime are normally a better match (and also offer the with()-methods). But if you still insist on ZonedDateTime then don't be too surprised if the set time-of-day during a summer-winter-time-switch deviates from what you finally observe in the resulting object because JSR-310 can make an automatic adjustment (push-forward-strategy), admittingly a rare case and extremely unlikely for market times..Tuft

© 2022 - 2024 — McMap. All rights reserved.