/** * Time vocabulary shared by the wire boundaries that accept a caller's zone. * Validation and canonicalization only: this library formats nothing and owns * no failure vocabulary — each boundary declares and throws its own refusal. * @module @deepseek-ai/dsh-util-time */ /** Strict browser-zone profile: UTC or an IANA Area/Location-style identifier. */ const IANA_TIME_ZONE = /^[A-Za-z][A-Za-z0-9_+.-]*(?:\/[A-Za-z0-9_+.-]+)+$/ /** * Validate and canonicalize one caller-supplied IANA zone at a wire boundary. * * The canonical name is what a later reader needs: a zone identity is stored on * durable records and resolved again by another process, so an alias accepted * here would not compare equal to the zone a reader derives. * @param value - the caller's reported zone name. * @returns the canonical zone, or `undefined` when the name is unusable. */ export function canonicalClientTimeZone(value: string): string | undefined { if (value.length === 0 || value.trim() !== value || (value !== 'UTC' && !IANA_TIME_ZONE.test(value))) return undefined try { const canonical = new Intl.DateTimeFormat('en-US', { timeZone: value }) .resolvedOptions().timeZone /* v8 ignore next -- Intl returns UTC or a canonical IANA Area/Location for accepted input. */ if (canonical !== 'UTC' && !IANA_TIME_ZONE.test(canonical)) return undefined return canonical } catch { // Intl rejects unsupported zone names; the caller maps that parser rejection. return undefined } }