Class BrowserTimeZone

java.lang.Object
com.vaadin.swingbridge.surrogates.BrowserTimeZone

public final class BrowserTimeZone extends Object
Surrogate-side cache for the browser's IANA time zone, populated from Vaadin's ExtendedClientDetails during UI init and read back by BrowserDateUtils.toLocalDate(Date) / BrowserDateUtils.toDate(LocalDate) on every Date ↔ LocalDate round-trip.

Migrators MUST call fetch() from a UI init listener before any view that uses SJSpinner(SpinnerDateModel) or SJFormattedDatePicker is reached. get() throws IllegalStateException if the cache is empty — a programming error (R_match_swing_errors, D_gap_severity_triage case-1 family, SD_browser_timezone), not a soft incompleteness. Failing loud here is much easier to diagnose than dates silently rendering an hour off because the server JVM's time zone diverged from the user's browser.

Slimmed Java port of karibu-tools' BrowserTimeZone.kt: we cache the derived ZoneId rather than the whole ExtendedClientDetails, since the surrogate layer only ever reads the zone, and tests install a deterministic zone via setZoneId(ZoneId) without fabricating a fake ECD.

  • Method Summary

    Modifier and Type
    Method
    Description
    static void
    Reads the current UI's cached ExtendedClientDetails; if already populated by Vaadin (placeholder values mean the browser hasn't responded yet — Vaadin uses screenWidth == -1 as the sentinel), derives the ZoneId synchronously.
    static ZoneId
    get()
    Returns the cached browser ZoneId.
    static ZoneId
    Lenient variant of get(): returns the cached browser ZoneId, or null when none is stored or no session is current — never throws.
    static void
    Stores the given zone in the current session.

    Methods inherited from class Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Method Details

    • fetch

      public static void fetch()
      Reads the current UI's cached ExtendedClientDetails; if already populated by Vaadin (placeholder values mean the browser hasn't responded yet — Vaadin uses screenWidth == -1 as the sentinel), derives the ZoneId synchronously. Otherwise triggers ExtendedClientDetails.refresh(SerializableConsumer) and stores the zone in the callback. No-op if the session already has a stored zone (typical on a refresh through @PreserveOnRefresh, or in tests where setZoneId(ZoneId) was called directly).

      Call this from a UI init listener — once per session is enough.

    • get

      public static ZoneId get()
      Returns the cached browser ZoneId. Throws if the cache is empty — BrowserDateUtils.toLocalDate(Date) / BrowserDateUtils.toDate(LocalDate) trust this to be populated, so a missing zone is a programming error (forgot to call fetch() during UI init).

      Convert a Date through BrowserDateUtils, not date.toInstant().atZone(get()). The DatePicker peers convert with java.util.TimeZone's arithmetic, which for pre-1900 dates differs from this ZoneId's local mean time by up to a day. Pure java.time seams (e.g. DateTimeFormatter.withZone(ZoneId) over a LocalDate) can take this value directly.

    • getOrNull

      public static ZoneId getOrNull()
      Lenient variant of get(): returns the cached browser ZoneId, or null when none is stored or no session is current — never throws. For callers that can fall back to a default zone rather than failing, e.g. vaadinx.EmulatorContext snapshotting the zone on a UI thread for background-thread propagation.

      Lock-safe. Reading VaadinSession.getAttribute(String) requires the session lock, so on a session-associated thread that doesn't hold it (e.g. Vaadin's license checker on a Jetty request-pool thread, or a SwingWorker reaching back through its session handle) this briefly acquires the lock, reads, and releases rather than throwing "Cannot access state … without locking" — honoring the never-throw contract and returning the real zone instead of a fallback. The session lock is reentrant, so the hasLock() fast path avoids a redundant re-lock when we already hold it.

    • setZoneId

      public static void setZoneId(ZoneId zone)
      Stores the given zone in the current session. Used internally by the fetch() callback; tests use it directly to install a deterministic zone without making a real browser round-trip.