Uuidv7Chrono

Convert between dates/datetimes and UUIDv7 for time-based Ecto database queries.

UUIDv7 encodes a Unix timestamp in its most significant bits, making primary keys naturally time-ordered. This library lets you generate UUIDv7 boundary values from a Date or DateTime, so you can efficiently filter records by time using simple primary key comparisons — no extra inserted_at index needed.

Installation

Add uuidv7_chrono to your list of dependencies in mix.exs:

def deps do
  [
    {:uuidv7_chrono, "~> 0.1.0"}
  ]
end

Usage

Filter Ecto queries by time

yesterday = Date.utc_today() |> Date.add(-1)

# Records created after yesterday
from(u in User, where: u.id > ^Uuidv7Chrono.to_uuid(yesterday))

# Records created before a specific timestamp
cutoff = ~U[2026-01-01 00:00:00Z]
from(o in Order, where: o.id < ^Uuidv7Chrono.to_uuid(cutoff))

Extract timestamps from UUIDv7

Uuidv7Chrono.to_datetime("019d2566-fe40-7000-8000-000000000000")
#=> ~U[2026-03-25 14:30:00.000Z]

Uuidv7Chrono.to_date("019d2566-fe40-7000-8000-000000000000")
#=> ~D[2026-03-25]

Both to_datetime/1 and to_date/1 accept string UUIDs ("019d2566-fe40-...") and raw 16-byte binary UUIDs.

Database partitioning

If your table is range-partitioned on a UUIDv7 primary key, these boundary values enable partition pruning — the database skips partitions that can't contain matching rows:

# Query only hits the Q1 2026 partition
from(o in Order,
  where: o.id >= ^Uuidv7Chrono.to_uuid(~D[2026-01-01])
    and o.id < ^Uuidv7Chrono.to_uuid(~D[2026-04-01])
)

Postgres-compatible aliases

If you prefer names that mirror the pg_uuidv7 Postgres extension:

Uuidv7Chrono.uuid_generate_v7(~U[2026-03-25 14:30:00Z])
Uuidv7Chrono.uuid_v7_to_timestamptz("019d2566-fe40-7000-8000-000000000000")

API

Function Description
to_uuid(Date.t() | DateTime.t()) Date/DateTime to UUIDv7 string
to_datetime(String.t() | binary()) UUIDv7 to DateTime
to_date(String.t() | binary()) UUIDv7 to Date
uuid_generate_v7/1 Alias for to_uuid/1 (pg_uuidv7 compat)
uuid_v7_to_timestamptz/1 Alias for to_datetime/1 (pg_uuidv7 compat)

How it works

to_uuid/1 encodes the timestamp as the first 48 bits of a UUIDv7 and fills the remaining bits with zeros. This produces the lowest possible UUIDv7 for that point in time, making it ideal as a boundary value in range queries.

Zero dependencies. Pure Elixir.

License

Apache-2.0