# UTC domains

Import from `@pibbl/core/viz`. UTC positions are numeric epoch milliseconds, not
`Date` objects. No runtime data fetching is required.

```ts
import {
  UTCScale,
  Axis,
  useUTCScale,
  utcTickLabels,
  type NumericDomain,
} from "@pibbl/core/viz";
const domain: NumericDomain = [Date.UTC(2025, 0, 1), Date.UTC(2026, 0, 1)];
declare function extent<D>(
  data: readonly D[],
  value: (
    datum: D,
    index: number,
    data: readonly D[],
  ) => number | null | undefined,
): NumericDomain | undefined;
declare function niceUTCDomain(
  domain: NumericDomain,
  options?: { count?: number },
): NumericDomain;
```

`extent` calls the accessor once per row, skips null/undefined, rejects other
nonfinite or nonnumeric results, and returns a frozen minimum/maximum pair.
Empty/all-missing data returns undefined. Singleton data returns equal endpoints.
It never sorts, mutates, subscribes, or caches.

`niceUTCDomain` expands epoch endpoints to enclosing UTC boundaries. Count defaults
to 5 and must be an integer 2–100. It preserves descending direction. A singleton
gets one millisecond padding on each side, or inward padding at Date limits.
Outward rounding beyond Date range throws; it never wraps a date. With count 2,
if no cadence can avoid an interior boundary (a domain straddling year zero),
niceness keeps the original integral-millisecond bounds.

## UTC Scale

`UTCScaleProps` shares `id`, `domain`, `range`, `reverse`, `style`, and `children`
with the linear scale and is provided by `UTCScale`. `NumericDomain` and `UtcDomain` are
readonly numeric pairs. UTC domain endpoints must be distinct safe integer
milliseconds inside ±8,640,000,000,000,000. Domain/range/reverse accept signals.

```tsx
<UTCScale id="date" domain={domain} range="width">
  <Axis
    scale="date"
    position="bottom"
    tickCount={5}
    tickFormat={(value) => new Date(Number(value)).toISOString().slice(0, 10)}
  />
</UTCScale>
```

`useUTCScale(id)` returns `Signal<ResolvedUtcScale>`.
Snapshots are frozen; signal identity survives data/allocation changes.

UTC `map`/`invert` use linear arithmetic with no clamp. Mapping accepts finite
fractional milliseconds inside Date range. A collapsed range cannot invert.
`ticks(count = 5)` accepts 2–100 and returns original endpoints plus aligned UTC
interior boundaries, using a cadence that fits the count. Axis handles counts
0 and 1. Month/year lengths are calendar-aware; weeks start Monday. The result
may have fewer ticks than requested and preserves descending order.

`formatTick(value)` returns deterministic full ISO UTC text, independent of prior
tick calls. Fractional milliseconds truncate toward zero for display only.
Use an Axis formatter for compact presentation; no automatic collision solver
or locale/time-zone selection is implied. Explicit Axis ticks remain numeric,
bounded, unique, in-domain, and in caller order.

Lines, points, custom plots, bar value scales, ScaleAdjust and numeric hover
queries accept either continuous kind. Missing-data gaps keep their existing
semantics. UTC is not browser-local calendar time; DST, IANA time zones, log
scales and automatic domain mutation remain separate work.

## Compact UTC labels

`utcTickLabels(values: readonly number[], options?: UTCTickLabelOptions): readonly string[]`
returns frozen labels in the same order, without modifying timestamps. `locale`
defaults to `"en-US"`; the calendar is Gregorian and the time zone is always UTC.
Use the returned array in `Axis.tickFormat={(_, index) => labels[index]}` with the
same `tickValues` array. Existing `useUTCScale(id).get().formatTick(value)` keeps
its full-ISO contract.

The complete set determines precision: January 1 midnight ticks use years;
first-of-month midnight ticks use month/year; other midnight ticks use
month/day/year; sub-day ticks also include 24-hour hour/minute, adding seconds
and three millisecond digits when present. Every label keeps its year and any
necessary date, so collision skipping never removes essential calendar context.
An era is included for all labels when any input is in year zero or earlier.
UTC should still be identified in the composition's title or units.

Empty input returns a frozen empty array. At most 100 safe-integer epoch
millisecond values within the JavaScript Date range are accepted; invalid input
throws `RangeError`. Duplicates and descending/arbitrary order are preserved.
Invalid locale options retain native Intl errors; punctuation follows host Intl
data. The helper accepts plain values, not signals. Read signal `.get()` in a
component/computed value to recompute; it acquires no resources or subscriptions.

```tsx
function DateAxis() {
  const ticks = useUTCScale("date").get().ticks(5);
  const labels = utcTickLabels(ticks);
  return (
    <Axis
      scale="date"
      position="bottom"
      tickValues={ticks}
      tickFormat={(_, index) => labels[index]}
      labelOverlap="skip"
    />
  );
}
```

The [minimal UTC demo](/playground/#/examples/composition/viz-utc-basics) is runnable and
editable with these labels.

## API details from source

<span id="api-extent"></span>

### extent

Computes a finite numeric extent in source order, skipping only null and undefined.

```ts
extent: <D>(data: readonly D[], value: (datum: D, index: number, data: readonly D[]) => number | null | undefined) => LinearDomain | undefined
```

Related API: [extent](/reference/functions/utc-domains/), [LinearDomain](/reference/components/scale/).

#### Parameters

- **`data`** — Source rows, which are never sorted or mutated.

- **`value`** — Accessor called once per row with its index and original array.

#### Returns

A frozen minimum/maximum pair, or undefined when every row is missing.

#### See also

[niceUTCDomain](/reference/functions/utc-domains/)

[View source — packages/core/src/features/viz/lib/utc-scale.ts:118](/source/packages/core/src/features/viz/lib/utc-scale-ts/#L118)

<span id="api-niceUTCDomain"></span>

### niceUTCDomain

Expands a numeric timestamp domain to enclosing UTC calendar boundaries.

```ts
niceUTCDomain: (domain: LinearDomain, options?: { readonly count?: number; }) => LinearDomain
```

Related API: [niceUTCDomain](/reference/functions/utc-domains/), [LinearDomain](/reference/components/scale/).

#### Parameters

- **`domain`** — Safe integer epoch-millisecond endpoints, possibly equal or descending.

- **`options`** — Optional bounded target tick count (default 5).

#### Returns

A frozen outward-rounded domain preserving its direction. See [LinearDomain](/reference/components/scale/).

#### See also

[UTCScale](/reference/components/scale/)

[View source — packages/core/src/features/viz/lib/utc-scale.ts:96](/source/packages/core/src/features/viz/lib/utc-scale-ts/#L96)

<span id="api-NumericDomain"></span>

### NumericDomain

Numeric endpoints shared by continuous scales. See LinearDomain.

```ts
type NumericDomain = LinearDomain
```

Related API: [NumericDomain](/reference/functions/utc-domains/), [LinearDomain](/reference/components/scale/).

[View source — packages/core/src/features/viz/lib/types.ts:149](/source/packages/core/src/features/viz/lib/types-ts/#L149)

<span id="api-UtcDomain"></span>

### UtcDomain

UTC timestamps use numeric epoch milliseconds. See LinearDomain.

```ts
type UtcDomain = LinearDomain
```

Related API: [UtcDomain](/reference/functions/utc-domains/), [LinearDomain](/reference/components/scale/).

[View source — packages/core/src/features/viz/lib/types.ts:147](/source/packages/core/src/features/viz/lib/types-ts/#L147)

<span id="api-UTCScaleProps"></span>

### UTCScaleProps

Calendar-aware UTC scale inputs. See LinearScaleProps.

```ts
type UTCScaleProps = LinearScaleProps
```

Related API: [UTCScaleProps](/reference/functions/utc-domains/), [LinearScaleProps](/reference/components/scale/).

[View source — packages/core/src/features/viz/lib/types.ts:151](/source/packages/core/src/features/viz/lib/types-ts/#L151)

#### Properties and methods

<span id="api-UTCScaleProps-id"></span>
<details>
<summary>id</summary>


```ts
readonly id: ScaleId
```

Related API: [ScaleId](/reference/components/scale/).

Stable identifier of this resource or connection. See ScaleId.

[View source — packages/core/src/features/viz/lib/types.ts:75](/source/packages/core/src/features/viz/lib/types-ts/#L75)

</details>

<span id="api-UTCScaleProps-domain"></span>
<details>
<summary>domain</summary>


```ts
readonly domain: SignalValue<LinearDomain>
```

Related API: [SignalValue](/reference/types/signal-inputs/#signalvalue), [LinearDomain](/reference/components/scale/).

Data values or endpoints accepted by the scale. See SignalValue, LinearDomain
.

[View source — packages/core/src/features/viz/lib/types.ts:80](/source/packages/core/src/features/viz/lib/types-ts/#L80)

</details>

<span id="api-UTCScaleProps-range"></span>
<details>
<summary>range</summary>


```ts
readonly range: SignalValue<ScaleRange>
```

Related API: [SignalValue](/reference/types/signal-inputs/#signalvalue), [ScaleRange](/reference/components/scale/).

Logical output coordinates produced by the scale. See SignalValue, ScaleRange
.

[View source — packages/core/src/features/viz/lib/types.ts:85](/source/packages/core/src/features/viz/lib/types-ts/#L85)

</details>

<span id="api-UTCScaleProps-reverse"></span>
<details>
<summary>reverse (optional)</summary>


```ts
readonly reverse?: SignalValue<boolean> | undefined
```

Related API: [SignalValue](/reference/types/signal-inputs/#signalvalue).

Whether to reverse the direction of the mapping or guide. See SignalValue.

[View source — packages/core/src/features/viz/lib/types.ts:87](/source/packages/core/src/features/viz/lib/types-ts/#L87)

</details>

<span id="api-UTCScaleProps-style"></span>
<details>
<summary>style (optional)</summary>


<details>
<summary>Full type declaration</summary>

```ts
readonly style?: SignalValue<Readonly<{ left?: SignalValue<number | `${number}%` | undefined>; top?: SignalValue<number | `${number}%` | undefined>; width?: SignalValue<Length | undefined>; height?: SignalValue<Length | undefined>; alignSelf?: SignalValue<"auto" | "center" | "end" | "flex-end" | "flex-start" | "start" | "stretch" | undefined>; justifySelf?: SignalValue<"auto" | "center" | "end" | "start" | "stretch" | undefined>; flexBasis?: SignalValue<Length | undefined>; flexGrow?: SignalValue<number | undefined>; flexShrink?: SignalValue<number | undefined>; gridColumnStart?: SignalValue<number | undefined>; gridColumnSpan?: SignalValue<number | undefined>; gridRowStart?: SignalValue<number | undefined>; gridRowSpan?: SignalValue<number | undefined>; transition?: SignalValue<PibblTransitionBinding | undefined>; custom?: unknown; filter?: SignalValue<PibblFilter | readonly PibblFilter[] | undefined>; }>> | undefined
```

</details>

Related API: [SignalValue](/reference/types/signal-inputs/#signalvalue), [Length](/reference/types/layout/#length), [PibblTransitionBinding](/reference/hooks/use-visibility-transition/), [PibblFilter](/reference/types/filters/#pibblfilter).

Declared presentation and layout properties. See SignalValue, SignalStyle,
ScaleLayoutStyle.

[View source — packages/core/src/features/viz/lib/types.ts:92](/source/packages/core/src/features/viz/lib/types-ts/#L92)

</details>

<span id="api-UTCScaleProps-children"></span>
<details>
<summary>children (optional)</summary>


```ts
readonly children?: PibblNode
```

Related API: [PibblNode](/reference/types/elements-components/#pibblnode).

Descendant content or the callback that supplies it. See PibblNode.

[View source — packages/core/src/features/viz/lib/types.ts:94](/source/packages/core/src/features/viz/lib/types-ts/#L94)

</details>

<span id="api-ResolvedUtcScale"></span>

### ResolvedUtcScale

UTC continuous mapping with stateless ISO formatting. See ResolvedLinearScale.

```ts
interface ResolvedUtcScale extends Omit<ResolvedLinearScale, "type">
```

Related API: [ResolvedUtcScale](/reference/functions/utc-domains/), [ResolvedLinearScale](/reference/components/scale/).

[View source — packages/core/src/features/viz/lib/types.ts:227](/source/packages/core/src/features/viz/lib/types-ts/#L227)

#### Properties and methods

<span id="api-ResolvedUtcScale-type"></span>
<details>
<summary>type</summary>


```ts
readonly type: "utc"
```

UTC calendar scale discriminant. See UTCScaleProps.

[View source — packages/core/src/features/viz/lib/types.ts:229](/source/packages/core/src/features/viz/lib/types-ts/#L229)

</details>

<span id="api-ResolvedUtcScale-formatTick"></span>
<details>
<summary>formatTick</summary>


```ts
formatTick: (value: number) => string
```

Formats a timestamp as full UTC ISO text without changing tick geometry.

##### Parameters

- **`value`** — Finite epoch milliseconds inside the Date range.

##### Returns

ISO text with millisecond precision. See [ResolvedUtcScale](/reference/functions/utc-domains/).

[View source — packages/core/src/features/viz/lib/types.ts:235](/source/packages/core/src/features/viz/lib/types-ts/#L235)

</details>

<span id="api-ResolvedUtcScale-domain"></span>
<details>
<summary>domain</summary>


```ts
readonly domain: LinearDomain
```

Related API: [LinearDomain](/reference/components/scale/).

Data values or endpoints accepted by the scale. See LinearDomain.

[View source — packages/core/src/features/viz/lib/types.ts:193](/source/packages/core/src/features/viz/lib/types-ts/#L193)

</details>

<span id="api-ResolvedUtcScale-range"></span>
<details>
<summary>range</summary>


```ts
readonly range: readonly [number, number]
```

Logical output coordinates produced by the scale. See ResolvedLinearScale.

[View source — packages/core/src/features/viz/lib/types.ts:195](/source/packages/core/src/features/viz/lib/types-ts/#L195)

</details>

<span id="api-ResolvedUtcScale-frame"></span>
<details>
<summary>frame</summary>


```ts
readonly frame: Readonly<LayoutBox>
```

Related API: [LayoutBox](/reference/types/layout/#layoutbox).

Resolved layout frame containing the scale. See LayoutBox.

[View source — packages/core/src/features/viz/lib/types.ts:197](/source/packages/core/src/features/viz/lib/types-ts/#L197)

</details>

<span id="api-ResolvedUtcScale-map"></span>
<details>
<summary>map</summary>


```ts
map: (value: number) => number
```

Maps a numeric domain value to a logical range coordinate. See ResolvedLinearScale.

##### Parameters

- **`value`** — Numeric domain coordinate.

##### Returns

The corresponding range coordinate.

[View source — packages/core/src/features/viz/lib/types.ts:203](/source/packages/core/src/features/viz/lib/types-ts/#L203)

</details>

<span id="api-ResolvedUtcScale-invert"></span>
<details>
<summary>invert</summary>


```ts
invert: (pixel: number) => number
```

Related API: [invert](/reference/types/filters/#invert).

Maps a logical range coordinate back into the numeric domain. See ResolvedLinearScale
.

##### Parameters

- **`pixel`** — Coordinate in the scale's pixel range.

##### Returns

The corresponding numeric domain value.

[View source — packages/core/src/features/viz/lib/types.ts:210](/source/packages/core/src/features/viz/lib/types-ts/#L210)

</details>

<span id="api-ResolvedUtcScale-ticks"></span>
<details>
<summary>ticks</summary>


```ts
ticks: (count?: number) => readonly number[]
```

Returns representative numeric tick values for the requested count. See
ResolvedLinearScale.

##### Parameters

- **`count`** — Suggested number of ticks.

##### Returns

Tick values in domain coordinates.

[View source — packages/core/src/features/viz/lib/types.ts:217](/source/packages/core/src/features/viz/lib/types-ts/#L217)

</details>

<span id="api-ResolvedContinuousScale"></span>

### ResolvedContinuousScale

Any supported numeric mapping. See ResolvedUtcScale.

```ts
type ResolvedContinuousScale = | ResolvedLinearScale
  | ResolvedUtcScale
  | ResolvedLogScale
  | ResolvedSymlogScale
```

Related API: [ResolvedContinuousScale](/reference/functions/utc-domains/), [ResolvedLinearScale](/reference/components/scale/), [ResolvedUtcScale](/reference/functions/utc-domains/), [ResolvedLogScale](/reference/components/log-scale/), [ResolvedSymlogScale](/reference/components/symlog-point-scales/).

[View source — packages/core/src/features/viz/lib/types.ts:238](/source/packages/core/src/features/viz/lib/types-ts/#L238)

#### Properties and methods

<span id="api-ResolvedContinuousScale-type"></span>
<details>
<summary>type</summary>


```ts
readonly type: "linear" | "log" | "symlog" | "utc"
```

The literal "linear" identifying this variant. See ResolvedLinearScale.
Logarithmic mapping discriminant. See LogScaleProps.
Signed logarithmic discriminant. See SymlogScaleProps.
UTC calendar scale discriminant. See UTCScaleProps.

[View source — packages/core/src/features/viz/lib/types.ts:191](/source/packages/core/src/features/viz/lib/types-ts/#L191)

</details>

<span id="api-ResolvedContinuousScale-domain"></span>
<details>
<summary>domain</summary>


```ts
readonly domain: LinearDomain
```

Related API: [LinearDomain](/reference/components/scale/).

Data values or endpoints accepted by the scale. See LinearDomain.

[View source — packages/core/src/features/viz/lib/types.ts:193](/source/packages/core/src/features/viz/lib/types-ts/#L193)

</details>

<span id="api-ResolvedContinuousScale-range"></span>
<details>
<summary>range</summary>


```ts
readonly range: readonly [number, number]
```

Logical output coordinates produced by the scale. See ResolvedLinearScale.

[View source — packages/core/src/features/viz/lib/types.ts:195](/source/packages/core/src/features/viz/lib/types-ts/#L195)

</details>

<span id="api-ResolvedContinuousScale-frame"></span>
<details>
<summary>frame</summary>


```ts
readonly frame: Readonly<LayoutBox>
```

Related API: [LayoutBox](/reference/types/layout/#layoutbox).

Resolved layout frame containing the scale. See LayoutBox.

[View source — packages/core/src/features/viz/lib/types.ts:197](/source/packages/core/src/features/viz/lib/types-ts/#L197)

</details>

<span id="api-ResolvedContinuousScale-map"></span>
<details>
<summary>map</summary>


```ts
map: (value: number) => number
```

Maps a numeric domain value to a logical range coordinate. See ResolvedLinearScale.

##### Parameters

- **`value`** — Numeric domain coordinate.

##### Returns

The corresponding range coordinate.

[View source — packages/core/src/features/viz/lib/types.ts:203](/source/packages/core/src/features/viz/lib/types-ts/#L203)

</details>

<span id="api-ResolvedContinuousScale-invert"></span>
<details>
<summary>invert</summary>


```ts
invert: (pixel: number) => number
```

Related API: [invert](/reference/types/filters/#invert).

Maps a logical range coordinate back into the numeric domain. See ResolvedLinearScale
.

##### Parameters

- **`pixel`** — Coordinate in the scale's pixel range.

##### Returns

The corresponding numeric domain value.

[View source — packages/core/src/features/viz/lib/types.ts:210](/source/packages/core/src/features/viz/lib/types-ts/#L210)

</details>

<span id="api-ResolvedContinuousScale-ticks"></span>
<details>
<summary>ticks</summary>


```ts
ticks: (count?: number) => readonly number[]
```

Returns representative numeric tick values for the requested count. See
ResolvedLinearScale.

##### Parameters

- **`count`** — Suggested number of ticks.

##### Returns

Tick values in domain coordinates.

[View source — packages/core/src/features/viz/lib/types.ts:217](/source/packages/core/src/features/viz/lib/types-ts/#L217)

</details>

<span id="api-utcTickLabels"></span>

### utcTickLabels

Creates compact labels with calendar context retained on every tick.

```ts
utcTickLabels: (values: readonly number[], options?: UTCTickLabelOptions) => readonly string[]
```

Related API: [utcTickLabels](/reference/functions/utc-domains/), [UTCTickLabelOptions](/reference/functions/utc-domains/).

#### Parameters

- **`values`** — At most 100 safe integer epoch milliseconds within Date range, in any order.

- **`options`** — Explicit locale; default en-US.

#### Returns

Frozen labels in input order. No geometry or scale state changes. See [UTCTickLabelOptions](/reference/functions/utc-domains/).

[View source — packages/core/src/features/viz/lib/utc-labels.ts:12](/source/packages/core/src/features/viz/lib/utc-labels-ts/#L12)

<span id="api-UTCTickLabelOptions"></span>

### UTCTickLabelOptions

Locale used for compact UTC tick text. See utcTickLabels.

```ts
interface UTCTickLabelOptions
```

Related API: [UTCTickLabelOptions](/reference/functions/utc-domains/).

[View source — packages/core/src/features/viz/lib/utc-labels.ts:2](/source/packages/core/src/features/viz/lib/utc-labels-ts/#L2)

#### Properties and methods

<span id="api-UTCTickLabelOptions-locale"></span>
<details>
<summary>locale (optional)</summary>


```ts
readonly locale?: string | undefined
```

BCP 47 locale, default en-US. Calendar is always Gregorian; time zone is UTC.

[View source — packages/core/src/features/viz/lib/utc-labels.ts:4](/source/packages/core/src/features/viz/lib/utc-labels-ts/#L4)

</details>

## Implementation guidance for agents

Read the [Data visualization companion](/agents/topics/visualization/) for ownership, adaptation, failure modes, and verification. [Agent start](/agents/) provides the version-selection workflow.

## Complete minimal examples

- [UTC dates across New Year](/minimal-examples/viz/utc-numeric/): Keep month, day, and year visible when a calendar axis crosses into a new year. [Plain source](/minimal/viz/utc-numeric.tsx)
- [UTC scales and domain helpers](/minimal-examples/viz/utc/): Render real NOAA observations with UTC calendar ticks, numeric extents and outward domain rounding. [Plain source](/minimal/viz/utc.tsx)
## Documentation version

Documentation built with @pibbl/core 0.0.2, revision 272a94a. ALPHA — NOT FOR PRODUCTION USE.
