UNPKG

@burglekitt/gmt

Version:

Temporal-based date and time utilities with timezone support and polyfill integration

45 lines (44 loc) 2.02 kB
import { Temporal } from "@js-temporal/polyfill"; import { isValidZonedDateTime } from "../validate/index.js"; const NANOSECONDS_PER_MINUTE = 60_000_000_000; function isValidZonedOffsetUnit(unit) { return unit === "minutes" || unit === "nanoseconds"; } /** * Read a zoned value's UTC offset as a number, in the given unit. * * - Subsumes what would otherwise be `getZonedOffsetMinutes` / * `getZonedOffsetNanoseconds` — one differently-scaled reading of the same * underlying quantity through a single parameterized call, following J8's * `getDurationUnit(value, unit)` precedent (Decision 5). * - "nanoseconds" reads Temporal's `offsetNanoseconds` directly. * - "minutes" divides by 60e9 — every IANA offset is a whole number of * minutes, so this never truncates a fraction. * - Negative offsets (west of UTC) return a negative number. * - Returns null on invalid `value` or `unit`. * * @param value zoned ISO 8601 datetime string * @param unit "minutes" | "nanoseconds" * @returns the offset in the requested unit, or null on invalid input * * @example getZonedOffsetAs("2024-07-15T12:00:00-04:00[America/New_York]", "minutes") // -240 * @example getZonedOffsetAs("2024-05-15T12:00:00+05:45[Asia/Kathmandu]", "minutes") // 345 * @example getZonedOffsetAs("2024-02-29T12:00:00+00:00[UTC]", "nanoseconds") // 0 * @example getZonedOffsetAs("2024-07-15T12:00:00-04:00[America/New_York]", "nanoseconds") // -14400000000000 * @example getZonedOffsetAs("invalid", "minutes") // null * @example getZonedOffsetAs("2024-02-29T12:00:00+00:00[UTC]", "fortnights" as never) // null */ export function getZonedOffsetAs(value, unit) { if (!isValidZonedDateTime(value) || !isValidZonedOffsetUnit(unit)) { return null; } try { const { offsetNanoseconds } = Temporal.ZonedDateTime.from(value); return unit === "nanoseconds" ? offsetNanoseconds : offsetNanoseconds / NANOSECONDS_PER_MINUTE; } catch { return null; } }