'How to make Ecto interpret/write local time instead of UTC for `timestamps` macro
This is about integrating a database from a legacy app.
The legacy app is reading and writing timestamps (i.e. created_at, updated_at in local time of the host).
And while I'm fully aware that this should be highly avoided this behaviour cannot be changed.
Therefore the Elixir application that uses the same database must be configured to use local time as well.
Ecto provides the timestamps macro but it seems that I cannot make it work with local timestamps.
While it's possible to provide a type (i.e. :naive_datetime or :utc_datetime) both types seem to use the utc_now() function.
Also reading the fields might cause difficulties, since the date fields are defined as timestamp without time zone in the database.
Hence the database fields also should be interpreted as local time and not as UTC.
Solution 1:[1]
Per @AlekseiMatiushkin, you should be able to use the :autogenerate for this, something like:
defmodule MyThing do
use Ecto.Schema
schema "things" do
field(:something, :string, null: false)
# ...
timestamps(autogenerate: {MyThing, :local_time, []})
end
def local_time do
DateTime.now!("Europe/Vienna") |> DateTime.to_naive()
end
# ...
end
If relying on the macro is too constrained for your use-case, you can manually write values to the fields (some languages call these mutations, virtual fields, or calculated fields). Something like:
defmodule MyThing do
use Ecto.Schema
import Ecto.Changeset
schema "things" do
field(:something, :string, null: false)
field(:my_timestamp_col, :map) # <-- or integer, or ???
# ...
end
def changeset(thing, attrs) do
thing
|> cast(
attrs,
[
:something,
# ...
]
)
# validate, constraints, etc.
|> calc_local_time()
end
defp calc_local_time(changeset) do
case changeset do
%Ecto.Changeset{
valid?: true,
changes: thing
} ->
put_change(thing, :my_timestamp_col, local_time())
_ ->
changeset
end
end
def local_time do
# add custom date/time calcs here
DateTime.now!("Europe/Vienna") |> DateTime.to_naive()
end
end
Hopefully you can find a solution leveraging the above patterns.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Everett |
