Packages
postgrex
0.15.1
1.0.0-rc.1
retired
1.0.0-rc.0
retired
0.22.3
0.22.2
0.22.1
0.22.0
0.21.1
0.21.0
0.20.0
0.19.3
0.19.2
0.19.1
0.19.0
0.18.0
0.17.5
0.17.4
0.17.3
0.17.2
0.17.1
0.17.0
0.16.5
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.13
0.15.12
0.15.11
0.15.10
0.15.9
0.15.8
0.15.7
0.15.6
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.3
0.14.2
0.14.1
0.14.0
0.14.0-rc.1
0.14.0-rc.0
0.13.5
0.13.4
0.13.3
0.13.2
0.13.1
0.13.0
0.13.0-rc.0
0.12.2
0.12.1
0.12.0
0.11.2
0.11.1
0.11.0
0.10.0
0.9.1
0.9.0
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.0
0.6.0
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.2
PostgreSQL driver for Elixir
Current section
Files
Jump to
Current section
Files
lib/postgrex/extensions/timestamp.ex
defmodule Postgrex.Extensions.Timestamp do
@moduledoc false
import Postgrex.BinaryUtils, warn: false
use Postgrex.BinaryExtension, send: "timestamp_send"
@gs_epoch :calendar.datetime_to_gregorian_seconds({{2000, 1, 1}, {0, 0, 0}})
@max_year 294_276
def encode(_) do
quote location: :keep do
%NaiveDateTime{calendar: Calendar.ISO} = naive ->
unquote(__MODULE__).encode_elixir(naive)
%DateTime{calendar: Calendar.ISO} = dt ->
unquote(__MODULE__).encode_elixir(dt)
other ->
raise DBConnection.EncodeError,
Postgrex.Utils.encode_msg(other, {DateTime, NaiveDateTime})
end
end
def decode(_) do
quote location: :keep do
<<8::int32, microsecs::int64>> ->
unquote(__MODULE__).microsecond_to_elixir(microsecs)
end
end
## Helpers
def encode_elixir(%_{
year: year,
month: month,
day: day,
hour: hour,
minute: min,
second: sec,
microsecond: {usec, _}
})
when year <= @max_year and hour in 0..23 and min in 0..59 and sec in 0..59 and
usec in 0..999_999 do
datetime = {{year, month, day}, {hour, min, sec}}
secs = :calendar.datetime_to_gregorian_seconds(datetime) - @gs_epoch
<<8::int32, secs * 1_000_000 + usec::int64>>
end
def microsecond_to_elixir(microsecs) do
{erl_datetime, microsecs} = split(microsecs)
NaiveDateTime.from_erl!(erl_datetime, {microsecs, 6})
end
defp split(microsecs) when microsecs < 0 and rem(microsecs, 1_000_000) != 0 do
secs = div(microsecs, 1_000_000) - 1
microsecs = 1_000_000 + rem(microsecs, 1_000_000)
split(secs, microsecs)
end
defp split(microsecs) do
secs = div(microsecs, 1_000_000)
microsecs = rem(microsecs, 1_000_000)
split(secs, microsecs)
end
defp split(secs, microsecs) do
{:calendar.gregorian_seconds_to_datetime(secs + @gs_epoch), microsecs}
end
end