Time Zones and Daylight Saving Time

Time Zones and Daylight Saving Time


Overview

LocalDate, LocalTime, and LocalDateTime have no concept of time zone. When time-zone awareness is needed, use:

Class Description
ZoneId Identifier for a time zone (e.g., "America/New_York")
ZoneOffset A fixed UTC offset (e.g., +05:30)
ZonedDateTime Date and time with a time zone
OffsetDateTime Date and time with a fixed UTC offset (no DST rules)

ZoneId

ZoneId names a region-based time zone that follows the IANA Time Zone Database (also called the tz database).

java
ZoneId newYork = ZoneId.of("America/New_York"); ZoneId london = ZoneId.of("Europe/London"); ZoneId utc = ZoneId.of("UTC"); ZoneId system = ZoneId.systemDefault(); // List available IDs Set<String> allIds = ZoneId.getAvailableZoneIds();

ZoneOffset represents a fixed offset from UTC — it does not adjust for DST:

java
ZoneOffset plus5 = ZoneOffset.of("+05:30"); // India Standard Time offset ZoneOffset utc = ZoneOffset.UTC; // +00:00 ZoneOffset minus5 = ZoneOffset.ofHours(-5); // EST offset (no DST)

ZonedDateTime

ZonedDateTime holds a LocalDateTime, a ZoneId, and the effective ZoneOffset. It is the full date-time with time-zone rules applied.

Creating a ZonedDateTime

java
// Now in a specific zone ZonedDateTime now = ZonedDateTime.now(ZoneId.of("America/New_York")); // From a LocalDateTime LocalDateTime ldt = LocalDateTime.of(2025, 6, 15, 10, 30); ZonedDateTime zdt = ldt.atZone(ZoneId.of("America/Chicago")); // CDT = UTC-5 // From an Instant Instant ts = Instant.now(); ZonedDateTime fromInstant = ts.atZone(ZoneId.of("Europe/Paris")); // Explicit factory ZonedDateTime explicit = ZonedDateTime.of(2025, 6, 15, 10, 30, 0, 0, ZoneId.of("Asia/Tokyo"));

Reading a ZonedDateTime

java
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("America/New_York")); zdt.toLocalDate(); // LocalDate zdt.toLocalTime(); // LocalTime zdt.toLocalDateTime(); // LocalDateTime (no zone) zdt.getZone(); // ZoneId zdt.getOffset(); // ZoneOffset (e.g., -04:00 during EDT) zdt.toInstant(); // Instant (UTC equivalent)

Converting Between Time Zones

java
ZonedDateTime nyTime = ZonedDateTime.of( LocalDateTime.of(2025, 6, 15, 9, 0), ZoneId.of("America/New_York")); // Convert to another zone — same instant, different local time ZonedDateTime londonTime = nyTime.withZoneSameInstant(ZoneId.of("Europe/London")); ZonedDateTime tokyoTime = nyTime.withZoneSameInstant(ZoneId.of("Asia/Tokyo")); System.out.println(nyTime); // 2025-06-15T09:00-04:00[America/New_York] System.out.println(londonTime); // 2025-06-15T14:00+01:00[Europe/London] System.out.println(tokyoTime); // 2025-06-15T22:00+09:00[Asia/Tokyo]

Exam tip: withZoneSameInstant() converts the moment to another zone — the underlying Instant stays the same. withZoneSameLocal() keeps the same local clock reading but in a different zone — the Instant changes.


Daylight Saving Time (DST)

Daylight Saving Time is a seasonal adjustment where clocks are moved forward in spring and back in autumn. ZonedDateTime applies DST rules automatically.

Spring-Forward (Gap)

When clocks spring forward, a range of local times is skipped (a gap). Constructing a ZonedDateTime in the gap adjusts it forward automatically:

java
// In America/New_York, clocks spring forward on 2025-03-09 at 02:00 → 03:00 ZonedDateTime inGap = LocalDateTime.of(2025, 3, 9, 2, 30) .atZone(ZoneId.of("America/New_York")); System.out.println(inGap); // 2025-03-09T03:30-04:00[America/New_York] (adjusted forward)

Fall-Back (Overlap)

When clocks fall back, a range of local times is repeated (an overlap). The earlier offset (DST) is used by default when constructing a ZonedDateTime in the overlap:

java
// In America/New_York, clocks fall back on 2025-11-02 at 02:00 → 01:00 // 01:30 occurs twice: once in EDT (-04:00) and once in EST (-05:00) ZonedDateTime overlap = LocalDateTime.of(2025, 11, 2, 1, 30) .atZone(ZoneId.of("America/New_York")); System.out.println(overlap); // 2025-11-02T01:30-04:00[America/New_York] (earlier, DST offset used by default) // Move to the later offset (standard time): ZonedDateTime later = overlap.withLaterOffsetAtOverlap(); System.out.println(later); // 2025-11-02T01:30-05:00[America/New_York]

Arithmetic Across DST Transitions

ZonedDateTime arithmetic respects DST transitions. Adding Duration preserves the elapsed time; adding Period or using date-based methods preserves the local clock reading:

java
ZonedDateTime beforeSpring = ZonedDateTime.of( LocalDateTime.of(2025, 3, 9, 1, 30), ZoneId.of("America/New_York")); // EST: -05:00 // Add 1 hour via Duration — spans the gap, 1 real hour elapsed ZonedDateTime afterDuration = beforeSpring.plus(Duration.ofHours(1)); System.out.println(afterDuration); // 2025-03-09T03:30-04:00 (1 hour later in clock time is 3:30 EDT) // Add 1 day — same local time the next day ZonedDateTime nextDay = beforeSpring.plusDays(1); System.out.println(nextDay); // 2025-03-10T01:30-04:00 (same clock reading, now EDT)

OffsetDateTime

OffsetDateTime stores date, time, and a fixed UTC offset (ZoneOffset). Unlike ZonedDateTime, it does not follow DST rules:

java
OffsetDateTime odt = OffsetDateTime.of( LocalDateTime.of(2025, 6, 15, 10, 30), ZoneOffset.of("+05:30")); System.out.println(odt); // 2025-06-15T10:30+05:30 odt.toInstant(); // Instant (UTC equivalent) odt.toZonedDateTime(); // ZonedDateTime with a fixed offset zone

Key Points for the Exam

  • ZoneId uses IANA names (e.g., "America/New_York"); ZoneOffset is a fixed offset (e.g., "+05:30").
  • ZonedDateTime applies DST rules automatically; OffsetDateTime uses a fixed offset.
  • withZoneSameInstant() — same moment, different local time; withZoneSameLocal() — same local time, different moment.
  • Spring-forward gaps: a local time in the gap is adjusted forward to the first valid time after the transition.
  • Fall-back overlaps: by default, the earlier (DST) offset is used; use withLaterOffsetAtOverlap() for the later (standard) offset.
  • Adding Duration to ZonedDateTime measures elapsed wall-clock seconds; adding date/time fields preserves local clock reading.
  • Instant is always UTC — it has no concept of time zone or DST.

References

v1.0·Last updated 2026-05-26