I have an object of ZonedDateTime
that is constructed like this
ZonedDateTime z = ZonedDateTime.of(LocalDate.now().atTime(11, 30), ZoneOffset.UTC);
How can I convert it to LocalDateTime
at time zone of Switzerland? Expected result should be 16 april 2018 13:30
.
Changing Timezones of ZonedDateTime To convert a ZonedDateTime instance from one timezone to another, follow the two steps: Create ZonedDateTime in 1st timezone. You may already have it in your application. Convert the first ZonedDateTime in second timezone using withZoneSameInstant() method.
The LocalDateTime has no time zone; to convert the LocalDateTime to ZonedDateTime , we can use . atZone(ZoneId. systemDefault()) to create a ZonedDateTime containing the system default time zone and convert it to another time zone using a predefined zone id or offset.
In your case: // your local date/time with no timezone information LocalDateTime localNow = LocalDateTime. now(); // setting UTC as the timezone ZonedDateTime zonedUTC = localNow. atZone(ZoneId.
A ZonedDateTime represents a date-time with a time offset and/or a time zone in the ISO-8601 calendar system. On its own, ZonedDateTime only supports specifying time offsets such as UTC or UTC+02:00 , plus the SYSTEM time zone ID.
How can I convert it to LocalDateTime at time zone of Switzerland?
You can convert the UTC ZonedDateTime
into a ZonedDateTime
with the time zone of Switzerland, but maintaining the same instant in time, and then get the LocalDateTime
out of that, if you need to. I'd be tempted to keep it as a ZonedDateTime
unless you need it as a LocalDateTime
for some other reason though.
ZonedDateTime utcZoned = ZonedDateTime.of(LocalDate.now().atTime(11, 30), ZoneOffset.UTC);
ZoneId swissZone = ZoneId.of("Europe/Zurich");
ZonedDateTime swissZoned = utcZoned.withZoneSameInstant(swissZone);
LocalDateTime swissLocal = swissZoned.toLocalDateTime();
It helps to understand the difference between LocalDateTime and ZonedDateTime. What you really want is a ZonedDateTime
. If you wanted to remove the timezone from the string representation, you would convert it to a LocalDateTime
.
What you're looking for is:
ZonedDateTime swissZonedDateTime = withZoneSameInstant(ZoneId.of("Europe/Zurich"));
LocalDateTime - this is basically a glorified string representation of a Date
and Time
; it is timezone agnostic, which means it does not represent any point in time on a timeline
Instant - this is a millisecond representation of time that has elapsed since EPOCH. This represents a specific instant in time on a timeline
ZonedDateTime - this also represents an instant in time on a timeline, but it represents it as a Date
and Time
with a TimeZone
.
The code below illustrates how to use all 3.
LocalDateTime localDateTime = LocalDateTime.of(2018, 10, 25, 12, 00, 00); //October 25th at 12:00pm
ZonedDateTime zonedDateTimeInUTC = localDateTime.atZone(ZoneId.of("UTC"));
ZonedDateTime zonedDateTimeInEST = zonedDateTimeInUTC.withZoneSameInstant(ZoneId.of("America/New_York"));
System.out.println(localDateTime.toString()); // 018-10-25T12:00
System.out.println(zonedDateTimeInUTC.toString()); // 2018-10-25T12:00Z[UTC]
System.out.println(zonedDateTimeInEST.toString()); // 2018-10-25T08:00-04:00[America/New_York]
If you were to compare the Instant
values of both ZonedDateTimes
from above, they would be equivalent because they both point to the same instant in time. Somewhere in Greenwich (UTC timezone), it is noon on October 25th; at the same time, in New York, it would be 8 am (America/NewYork timezone).
Try this out. Substitute US/Central with your timezone.
ZonedDateTime z = ZonedDateTime.of(LocalDate.now().atTime(11, 30), ZoneOffset.UTC);
System.out.println(z.withZoneSameInstant(ZoneId.of("US/Central")));
Another option that seems a little more intuitive is to convert the zoned date to an instant, then use LocalDateTime.ofInstant:
ZonedDateTime zdt = ZonedDateTime.of(LocalDate.now().atTime(11, 30), ZoneOffset.UTC);
ZoneId zId = ZoneId.of("US/Central");
LocalDateTime l = LocalDateTime.ofInstant(zdt.toInstant(), zId);
I prefer this to withZoneSameInstant
because that solution little more opaque - you're getting a ZonedDateTime that has to be in a particular internal state (the correct time zone). Using ofInstant
can be used on any ZonedDateTime in any time zone.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With