Hello,
I have an existing postgres database (10) and want to output some bytes as json:
-
spec of output json for date time data type is iso 8601, utc, millisecond precision:
"2019-04-03T09:10:24.123Z"
-
schema to encode as json has 2 date time fields (opening_date, closing_date).
I use phoenix 1.4.3, ecto 3.1.0.
I use :utc_datetime_usec
data type, and values I pulled from database do indeed have micro second precision, so I output : "2019-04-03T09:10:24.123456Z"
, which is not supported downstream.
I considered following options:
a) drop to millisecond precision in view function
DateTime.truncate(v, :millisecond)
cons: require to map each field of type date time.
b) use custom ecto type, that drops precision at load time
in schema
field(:opening_date, UTCDateTimeMs)
defmodule UTCDateTimeMs do
@behaviour Ecto.Type
def type(), do: :utc_datetime_usec
def cast(term) do
Ecto.Type.cast(:utc_datetime_usec, term)
end
def load(term) do
case Ecto.Type.load(:utc_datetime_usec, term) do
{:ok, d} -> {:ok, DateTime.truncate(d, :millisecond)}
:error -> :error
end
end
def dump(term) do
Ecto.Type.dump(:utc_datetime_usec, term)
end
end
Then I do not have to map each field of this type but it drops precision too early…
c) configure json jason encoder to encode date time
Tried to redefine?
defimpl Jason.Encoder, for: DateTime do
def encode(value, _opts) do
[?\", value |> DateTime.truncate(:millisecond) |> DateTime.to_iso8601(), ?\"]
end
end
and I have 2 warnings:
warning: redefining module Jason.Encoder.DateTime (current version loaded from _build/dev/lib/jason/ebin/Elixir.Jason.Encoder.DateTime.beam)
lib/lift/hack_jason.ex:2
Generated lift app
warning: this clause cannot match because a previous clause at line 1 always matches
deps/jason/lib/encoder.ex:1
But my test is failing.
(And I do not like this approach redefining a module, it was scratch to see).
I’m currently using a) and ask for help on what a working c) would look like or any other option?
Cheers.