Java – Difference Between ZonedDateTime.withZoneSameInstant and ZonedDateTime.withZoneSameLocal

javajava-time

Let's say I have a ZonedDateTime:

ZonedDateTime zonedDateTime = 
     ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("US/Pacific"));

I would like to know which date/time it is let's say in Berlin.
I have two methods :

zonedDateTime.withZoneSameInstant(ZoneId.of("Europe/Berlin")); // probably this is the right one to get the corresponding date/time in Berlin

zonedDateTime.withZoneSameLocal(ZoneId.of("Europe/Berlin"));

The docs for the withZoneSameLocal method say: "The local date-time is only changed if it is invalid for the new zone…" and it's not clear when this really can happen (any example ? =)).

Which date/time each of them represents and what is the difference?

Best Answer

If you want to convert a timestamp from one timezone to another, use withZoneSameInstant(). withZoneSameLocal() will change the zone but keep all the other fields the same. The exception is where it would be an invalid date in that timezone.

For example,

ZonedDateTime dtUTC = ZonedDateTime.parse("2019-03-10T02:30:00Z");
ZoneId pacific = ZoneId.of("US/Pacific");
System.out.println(dtUTC.withZoneSameInstant(pacific));
System.out.println(dtUTC.withZoneSameLocal(pacific));

prints

2019-03-09T18:30-08:00[US/Pacific]
2019-03-10T03:30-07:00[US/Pacific]

The first line is the original timestamp converted to another timezone. The second tries to preserve the date/time fields, but 2:30 is not a valid time on that date (because of the Daylight Savings jump), so it shifts it by an hour.