How to construct ZonedDateTime from an Instant and a time string?
Asked Answered
B

3

8

Given an object of Instant, a time string representing the time at a specific ZoneId, How to construct a ZonedDateTime object with the date part (year, month, day) from the instant at the given ZoneId and the time part from the given time string?

For example:

Given an object of Instant of value 1437404400000 (equivalent to 20-07-2015 15:00 UTC), a time string 21:00, and an object of ZoneId representing Europe/London, I want to construct an object of ZonedDateTime equivalent to 20-07-2015 21:00 Europe/London.

Brnaby answered 23/7, 2015 at 16:49 Comment(7)
How do you want the date to be affected by the time, if at all?Blind
I want to extract the date part from the instant and the time part from the string. The time string represents the time at the specified time zone.Brnaby
But an instant doesn't have a date - it's just a point in time, which would be on different dates depending on the time zone. See my post for two options, basically...Blind
Yes, an instant doesn't have a date. I want to extract the date from it at the specified time zone and add the time from the time string (which is also at the specified time zone).Brnaby
Right, that isn't clear from the question - see my answer for two alternative interpretations, and their consequences.Blind
Thanks Jon, I've edited the question to make it clearer.Brnaby
Righto - I've simplified my answer to just the one then.Blind
B
10

You'll want to parse the time string to a LocalTime first, then you can adjust a ZonedDateTime from the Instant with the zone, and then apply the time. For example:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm", Locale.US);
LocalTime time = LocalTime.parse(timeText, formatter);
ZonedDateTime zoned = instant.atZone(zoneId)
                             .with(time);
Blind answered 23/7, 2015 at 16:54 Comment(0)
I
9

Create the instant and determine the date in UTC of that instant:

Instant instant = Instant.ofEpochMilli(1437404400000L);
LocalDate date = instant.atZone(ZoneOffset.UTC).toLocalDate();

// or if you want the date in the time zone at that instant:

ZoneId tz = ZoneId.of("Europe/London");
LocalDate date = instant.atZone(tz).toLocalDate();

Parse the time:

LocalTime time = LocalTime.parse("21:00");

Create a ZoneDateTime from the LocalDate and the LocalTime at the desired ZoneId:

ZonedDateTime zdt = ZonedDateTime.of(date, time, tz);

As pointed out by Jon you need to decide which date you want as the date in UTC may be different from the date in the given time zone at that instant.

Inappreciative answered 23/7, 2015 at 17:1 Comment(0)
M
1

In addition to the accepted answer and the one written by assylias, there is another simple way to achieve what you want.

You can use ZonedDateTime#ofInstant to obtain a ZonedDateTime from the Instant and then adjust it to the given time using ZonedDateTime#with.

ZonedDateTime.ofInstant(Instant.ofEpochMilli(1437404400000L), ZoneId.of("Europe/London"))
    .with(LocalTime.parse("21:00", DateTimeFormatter.ofPattern("HH:mm", Locale.ENGLISH)))

Demo

Expanded:

ZoneId zoneId = ZoneId.of("Europe/London");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm", Locale.ENGLISH);

Instant instant = Instant.ofEpochMilli(1437404400000L);
LocalTime time = LocalTime.parse("21:00", formatter);

ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, zoneId).with(time);

Learn about the modern Date-Time API from Trail: Date Time.

Michelson answered 9/10, 2022 at 21:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.