Tempo.Ecto.TempoRange (Tempo SQL v0.2.0)

Copy Markdown View Source

Ecto.ParameterizedType for the PostgreSQL composite type tempo_range — a tstzrange paired with a Tempo-resolution string and a jsonb metadata column that together preserve the full Tempo shape on round-trip.

CREATE TYPE tempo_range AS (
  range      tstzrange,
  resolution text,
  meta       jsonb
);

Use this type when you care about round-trip fidelity — the stored value round-trips as the same %Tempo.Interval{} including qualifications, non-Gregorian calendars, recurrence rules, zone identifiers, and the implicit-vs-explicit-span distinction.

Setup

Run the DDL helpers once, early in the migration history:

import Tempo.SQL.Migration
create_tempo_types()

Then declare columns with add_tempo_range/2 (or the raw add :window, :tempo_range).

Usage

schema "meetings" do
  field :window, Tempo.Ecto.TempoRange
end

Query API

The standard Postgres range operators (@>, &&) do not apply directly to a composite column — they must reach into (column).range. Use Tempo.Ecto.QueryAPI.Composite for fragments that auto-unwrap the composite; the plain Tempo.Ecto.QueryAPI does not work on these columns.

Fidelity

Round-trip preserves:

  • Token-list resolution (~o"2026Y" round-trips as ~o"2026Y", not a materialised interval).

  • Qualifications (:uncertain, :approximate).

  • Non-Gregorian calendars.

  • Recurrence rules and repeat rules.

  • Zone identifiers (IANA names preserved via the meta column, not just the UTC offset).

  • Tempo.Interval.metadata, provided it is JSON-serialisable.

Summary

Functions

Builds the parameterized-type tuple for use outside a schema.

Functions

cast_type(options \\ [])

Builds the parameterized-type tuple for use outside a schema.

See Tempo.Ecto.Interval.cast_type/1 for the schema-side equivalent and the full discussion.

Arguments

  • options is a keyword list of options.

Options

  • :resolution truncates the endpoints recorded in the composite to the given component. One of :year, :month, :day, :hour, :minute, or :second. Defaults to :second.

Returns

Examples

iex> Tempo.Ecto.TempoRange.cast_type()
{:parameterized, {Tempo.Ecto.TempoRange, %{resolution: :second}}}

iex> Tempo.Ecto.TempoRange.cast_type(resolution: :day)
{:parameterized, {Tempo.Ecto.TempoRange, %{resolution: :day}}}