Current section

Files

Jump to
closure_table examples ct_ecto deps postgrex lib postgrex extensions date.ex
Raw

examples/ct_ecto/deps/postgrex/lib/postgrex/extensions/date.ex

defmodule Postgrex.Extensions.Date do
@moduledoc false
import Postgrex.BinaryUtils, warn: false
use Postgrex.BinaryExtension, send: "date_send"
@gd_epoch :calendar.date_to_gregorian_days({2000, 1, 1})
@max_year 9999
@max_days 3_652_424
def encode(_) do
quote location: :keep do
%Date{calendar: Calendar.ISO} = date ->
unquote(__MODULE__).encode_elixir(date)
other ->
raise DBConnection.EncodeError, Postgrex.Utils.encode_msg(other, Date)
end
end
def decode(_) do
quote location: :keep do
<<4::int32, days::int32>> ->
unquote(__MODULE__).day_to_elixir(days)
end
end
## Helpers
def encode_elixir(%Date{year: year, month: month, day: day}) when year <= @max_year do
date = {year, month, day}
<<4::int32, :calendar.date_to_gregorian_days(date) - @gd_epoch::int32>>
end
def encode_elixir(%Date{} = date) do
raise ArgumentError, "#{inspect(date)} is beyond the maximum year #{@max_year}"
end
def day_to_elixir(days) do
days = days + @gd_epoch
if days in 0..@max_days do
days
|> :calendar.gregorian_days_to_date()
|> Date.from_erl!()
else
raise ArgumentError,
"Postgrex can only decode dates with days between 0 and #{@max_days}, got: #{
inspect(days)
}"
end
end
end