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 PostgreSQLdaterangecolumn. 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,jsonbin 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: :stringA 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
@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])}
@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).
@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.
@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"}