Answer
When converting a date‑time value between two time zones that have different offset definitions, Ceylon treats the underlying instant as immutable and recomputes the wall‑clock time using the offset rules of the target zone at that instant. The conversion therefore preserves the exact point in time while adjusting the displayed local time to reflect the target zone’s offset, including any DST shift that applies.
Confirmed facts
- Ceylon’s date‑time types delegate to the JVM’s {@code java.time} classes, so offset resolution follows the same rules as JSR‑310.
- A {@code ZoneId} is consulted against the JVM’s time‑zone database (TZDB) to obtain the correct {@code ZoneOffset} for the given instant, automatically applying DST adjustments where defined.
- If a fixed {@code OffsetDateTime} is used (no {@code ZoneId}), the offset is treated as a constant and is not adjusted when the system time zone changes or when converting to a zone with different rules.
- Conversion between {@code OffsetDateTime} and {@code ZonedDateTime} requires an explicit zone attachment; Ceylon does not infer a zone from a plain offset.
- The current offset of a zoneddatetime can be inspected via the {@code .offset} property, which reflects the zone‑derived offset at the moment the instance was created.
Steps to verify the behavior for a specific conversion
- Create a {@code LocalDateTime} representing the wall‑clock time you want to convert.
- Attach the source zone to obtain a {@code ZonedDateTime} (or create a fixed {@code OffsetDateTime} if you have a known offset).
- Convert to the target zone using the {@code .zoned} method with the target {@code ZoneId}.
- Print or compare the {@code .offset} values before and after conversion to see how the offset changed.
import ceylon.time.{LocalDateTime, ZoneId, ZonedDateTime};
void testConversion() {
LocalDateTime ldt = LocalDateTime.of(2026, 3, 29, 2, 30); // just before DST shift in Europe/Paris
ZonedDateTime src = ldt.zoned(ZoneId.of("Europe/Paris"));
print("Source offset: " + src.offset); // +01:00 (standard time)
ZonedDateTime tgt = src.zoned(ZoneId.of("America/New_York"));
print("Target offset: " + tgt.offset); // -04:00 (EDT, DST active)
// The instant is the same; only the wall‑clock time and offset differ.
}
Mechanism to verify precision of regional offsets
The library does not provide a separate “validation” API; instead, you can verify offset precision by:
- Inspecting the {@code .offset} property on the resulting {@code ZonedDateTime} or {@code OffsetDateTime}.
- Using {@code ZoneId.getRules().offsetOfInstant(instant)} to obtain the exact offset that the TZDB defines for a given instant.
- Comparing the two values; any discrepancy indicates a mismatch between the zone data used and the expected offset.
If you need to confirm that the JVM’s TZDB version matches a particular region’s historical offsets, you must check the underlying JVM’s time‑zone data (e.g., via {@code java.time.ZoneRulesProvider.getAvailableZoneIds()} and {@code ZoneRules.getVersion()}). This diagnostic detail would only change the recommendation if you suspect the JVM’s zone database is outdated or corrupted.