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.
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.
© 2022 - 2024 — McMap. All rights reserved.
LocalDateTime
andLocalTime
are normally a better match (and also offer thewith()
-methods). But if you still insist onZonedDateTime
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