Tempo.Ecto.TempoRange (Tempo SQL v0.4.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
);

A floating expression, with no zone and no time shift, is kept in tempo_floating_range, the same with a tsrange for its range: a field declared with frame: :floating.

Use this type when you care about round-trip fidelity: any expression with ISO 8601 text — a value, an interval, a recurrence, a set — round-trips as the same expression, including qualifications, calendars other than the Gregorian, recurrence rules, zone identifiers and the value-versus-interval distinction. The range column holds the stretch it covers, for queries.

Setup

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

import Tempo.SQL.Migration
create_tempo_types()

(and create_tempo_types(frame: :floating) for floating columns). Then declare columns with add_tempo_range/2 (or the raw add :window, :tempo_range).

Usage

schema "meetings" do
  field :window, Tempo.Ecto.TempoRange
  field :opening_hours, Tempo.Ecto.TempoRange, frame: :floating
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:

  • The resolution a value is written to (~o"2026Y" round-trips as ~o"2026Y", not as an interval between two instants).

  • 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).

  • The expression's metadata, and a set's members', provided each is JSON-serialisable.

Summary

Functions

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

Functions

cast_type(options \\ [])

@spec cast_type(keyword()) :: Ecto.Type.t()

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.

  • :frame is :utc (the default) for a tempo_range column, whose expressions are in a zone or at a time shift, or :floating for a tempo_floating_range column, whose expressions have neither.

Returns

Examples

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

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