A local date-time and region zone can have zero, one, or two valid offsets, so a saved offset must be checked against that zone's rules.
Java ZoneRules: validate a saved offset against a local booking
Reject mismatched booking data
An offset sent with a booking is useful during an autumn overlap, when the same local time occurs twice. It is not arbitrary. Check that the offset is among the region's valid offsets before creating the scheduled instant. A stale or forged offset can point to a different instant from the one implied by the region.
The fixture uses a Paris overlap with two accepted offsets and rejects +03:00. Gap and overlap detection introduces the transition rules; this lesson applies them to persisted input validation.
Separate validation from future rule changes
A future booking may be affected by time-zone database updates. Store the local intention, region, and chosen overlap policy. A saved instant is useful for current execution, but a long-lived recurring schedule may need recomputation when rules change.
Working program
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.zone.ZoneRules;
public class BookingOffsetGate {
static boolean accepted(LocalDateTime local, ZoneId region, ZoneOffset supplied) {
ZoneRules rules = region.getRules();
return rules.getValidOffsets(local).contains(supplied);
}
public static void main(String[] args) {
LocalDateTime booking = LocalDateTime.of(2024, 10, 27, 2, 30);
ZoneId paris = ZoneId.of("Europe/Paris");
System.out.println(accepted(booking, paris, ZoneOffset.ofHours(2)));
System.out.println(accepted(booking, paris, ZoneOffset.ofHours(1)));
System.out.println(accepted(booking, paris, ZoneOffset.ofHours(3)));
}
}Output
true
true
falseCost and ownership
Validation uses a small list of valid offsets and constant application storage. Zone-rule lookup is cheap for a single booking, but the rule database is versioned; policy and stored values must be reviewed when scheduling far into the future.
Common Mistakes
- Do not accept any syntactically valid offset for a region booking.
- Do not assume an overlap has only one valid instant.
- Do not store a bare LocalDateTime as the full identity of an overlapped booking.
Read next
Java daylight-saving transitions: reject gaps and choose overlaps, Java ZonedDateTime zone conversion: preserve the instant or the wall clock, Java date and time: local schedules versus instants, Java strict date parsing: reject impossible calendar input.
