Koyomi.DateRange (Koyomi v0.2.1)

Copy Markdown View Source

An Ecto type for a range of days. The value is a Date.Range with a step of 1, both ends included.

The :storage option says how the range is stored, so that the same field works with any database:

  • :postgres (the default) - a PostgreSQL daterange column. It needs :postgrex.
  • :string - a text column with an ISO 8601 interval, "2027-03-01/2027-03-07": SQLite, MySQL, and embedded schemas.
  • :map - a map column (JSON in SQLite and MySQL, jsonb in PostgreSQL) with %{"from" => "2027-03-01", "to" => "2027-03-07"}.
# PostgreSQL
add :stay, :daterange
field :stay, Koyomi.DateRange

# SQLite (ecto_sqlite3), MySQL
add :stay, :string
field :stay, Koyomi.DateRange, storage: :string

A string or a map sorts and compares as text, not as a range: a query for the ranges that hold a day needs PostgreSQL. With another database, two :date columns also work, with the from and to of Koyomi.Components.date_range_picker/1, and can be queried as dates.

The range picker posts the range as a map, %{"from" => "2027-03-01", "to" => "2027-03-07"}; the type also casts a map with "start" and "end", a Date.Range, a {first, last} tuple, an ISO 8601 interval ("2027-03-01/2027-03-07"), and the key of a built-in preset ("last_7_days", which a relative picker posts), as the days it covers today in UTC (see Koyomi.Presets.to_range/2 to count from another day). Both ends empty cast to nil. A range with one end, or with an end before its start, is invalid.

PostgreSQL keeps a daterange in its canonical form, [first, last + 1); the type writes that form and reads any form back as a Date.Range. A range without a bound (infinite) or an empty range reads back as nil.

Summary

Functions

Casts a value to a Date.Range (see the module docs for the forms it takes).

Dumps a range to a PostgreSQL daterange (Postgrex.Range), in its canonical form [first, last + 1).

Loads a PostgreSQL daterange (Postgrex.Range) of any form as a Date.Range; an infinite or empty range loads as nil.

The value of a range in the form that the picker reads and posts: %{"from" => iso, "to" => iso}, or empty strings for nil.

Functions

cast(map)

@spec cast(term()) :: {:ok, Date.Range.t() | nil} | :error | {:error, keyword()}

Casts a value to a Date.Range (see the module docs for the forms it takes).

Examples

iex> Koyomi.DateRange.cast("2027-03-01/2027-03-07")
{:ok, Date.range(~D[2027-03-01], ~D[2027-03-07])}

dump(range)

@spec dump(Date.Range.t() | nil) :: {:ok, term()} | :error

Dumps a range to a PostgreSQL daterange (Postgrex.Range), in its canonical form [first, last + 1).

load(range)

@spec load(term()) :: {:ok, Date.Range.t() | nil} | :error

Loads a PostgreSQL daterange (Postgrex.Range) of any form as a Date.Range; an infinite or empty range loads as nil.

to_params(arg1)

@spec to_params(Date.Range.t() | nil) :: %{required(String.t()) => String.t()}

The value of a range in the form that the picker reads and posts: %{"from" => iso, "to" => iso}, or empty strings for nil.

Examples

iex> Koyomi.DateRange.to_params(Date.range(~D[2027-03-01], ~D[2027-03-07]))
%{"from" => "2027-03-01", "to" => "2027-03-07"}