Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Java daylight-saving transitions: reject gaps and choose overlaps

Last updated: 29 Sept 20264 min read
tutorial
IntermediateBy AITrove Editorial

A ZoneRules instance maps local date-time values to valid offsets; a gap has no valid offset and an overlap can have two.

Download Java source kit

The complete program targets Java 8. Compile it as one source file; its output is checked against the lesson.

A local appointment is not yet an instant

A scheduler accepting a local appointment needs a region zone and a rule for daylight-saving changes. Automatically adjusting a nonexistent time can move a booking away from what the customer entered. Reject it when the application contract requires an exact local time.

This fixture uses known 2024 transitions in Europe/Paris. The March appointment has no matching offset. The October appointment has two, and each creates a different Instant from the same local fields. The region rules come from the runtime time-zone database; governments can change future rules.

Make the overlap policy visible

An offset is a numeric displacement, not a region rule. Persist the selected instant and the region when both execution and later display matter. If a future appointment must stay at a civil time even after a rule change, store that civil intent separately and define when it is recalculated.

The program displays both overlap instants rather than silently selecting one. A production input flow should ask for or clearly specify the earlier or later offset. A blanket UTC conversion before examining the local-time ambiguity loses evidence the service needs to make that choice.

Working program

Java
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.List;
public class AppointmentOffsets {
    public static void main(String[] args) {
        ZoneId zone = ZoneId.of("Europe/Paris");
        LocalDateTime gap = LocalDateTime.parse("2024-03-31T02:30:00");
        LocalDateTime overlap = LocalDateTime.parse("2024-10-27T02:30:00");
        System.out.println("gap offsets=" + zone.getRules().getValidOffsets(gap).size());
        List<ZoneOffset> offsets = zone.getRules().getValidOffsets(overlap);
        System.out.println("overlap offsets=" + offsets.size());
        for (ZoneOffset offset : offsets) System.out.println(overlap.toInstant(offset));
    }
}

Output

Output
gap offsets=0
overlap offsets=2
2024-10-27T00:30:00Z
2024-10-27T01:30:00Z

Costs and boundaries

The fixture stores at most two offsets per query. Region rules and their cached data are runtime resources; do not model them as a fixed application-owned lookup table for every future date.

Common Mistakes

  • Do not treat LocalDateTime as a unique instant.
  • A fixed ZoneOffset does not include regional daylight-saving rules.
  • Test gaps and overlaps separately.

Read next

Java date and time: local schedules versus instants, Java Clock: test expiry without sleeping, Configuration properties.

java
zone-transitions
Storage details