Convert Time Between Time Zones in Java
Problem
A ZonedDateTime pairs a date-time with a region's time-zone rules, so the same instant can be shown as the correct local time anywhere, daylight saving included.
A meeting starts at 09:30 on 9 March 2026 in India; show the local time for attendees in London, New York and Tokyo.
Java Program
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class ConvertTimeZones {
public static void main(String[] args) {
ZonedDateTime india = ZonedDateTime.of(LocalDateTime.of(2026, 3, 9, 9, 30), ZoneId.of("Asia/Kolkata"));
DateTimeFormatter f = DateTimeFormatter.ofPattern("d MMM yyyy HH:mm (xxx)", Locale.ENGLISH);
String[] zones = {"Asia/Kolkata", "Europe/London", "America/New_York", "Asia/Tokyo"};
for (String zone : zones) {
ZonedDateTime local = india.withZoneSameInstant(ZoneId.of(zone)); // same moment, different clock
System.out.println(String.format("%-17s %s", zone, local.format(f)));
}
}
}Output
Core Logic
withZoneSameInstant keeps the moment fixed and recalculates the wall-clock time for another zone.
- 1
ZonedDateTime.of(..., ZoneId.of("Asia/Kolkata"))fixes the meeting in Indian time (UTC+05:30). - 2For each target zone,
withZoneSameInstant(ZoneId.of(zone))converts it. - 3The
xxxpattern letter prints each zone's UTC offset. - 4
String.format("%-17s ...")pads the zone names into a neat column.
Key Point: Use region IDs such as America/New_York rather than fixed offsets like -05:00, so daylight-saving changes are applied for you.
Key Concepts
Approach 2: Starting from a UTC Instant
import java.time.Instant;
import java.time.ZoneId;
public class ConvertTimeZonesInstant {
public static void main(String[] args) {
Instant moment = Instant.parse("2026-03-09T04:00:00Z"); // a single point on the UTC timeline
System.out.println("UTC instant: " + moment);
System.out.println("In Kolkata: " + moment.atZone(ZoneId.of("Asia/Kolkata")).toLocalDateTime());
System.out.println("In New York: " + moment.atZone(ZoneId.of("America/New_York")).toLocalDateTime());
}
}
Output
Core Logic
Servers usually store times as an Instant — a point on the UTC timeline — and convert to a zone only when displaying it.
- 1
Instant.parse("2026-03-09T04:00:00Z")reads a UTC timestamp (theZmeans UTC). - 2
atZone(ZoneId.of(...))attaches a zone, producing aZonedDateTime. - 3
toLocalDateTime()drops the zone to show just the local clock reading.
Key Point: Store instants in UTC and convert at the edges; storing local times without a zone makes them ambiguous later.
Key Concepts
Interview Questions
What's the difference between withZoneSameInstant and withZoneSameLocal?
withZoneSameInstant keeps the moment and changes the clock reading. withZoneSameLocal keeps the clock reading and changes the moment.
How do you list all available time zones?
ZoneId.getAvailableZoneIds() returns every region ID, such as "Europe/London".