Lety Cruz
Lety Cruz

Reputation: 133

Add hours to a datetime field ecto elixir

Here is my model:

schema "fixtures" do
    field :sm_id, :integer
    field :local_score, :integer
    field :visitor_score, :integer
    field :local_pen_score, :integer
    field :visitor_pen_score, :integer
    field :ht_score, :string
    field :ft_score, :string
    field :et_score, :string
    field :starting_at, Ecto.DateTime
    belongs_to :local_team, Team, foreign_key: :local_team_id
    belongs_to :visitor_team, Team, foreign_key: :visitor_team_id
    belongs_to :season, Season
    belongs_to :round, Round

    timestamps()
end

What I want is to get the live fixtures using the following query:

def fixtures_live(query, round_) do
    now = Ecto.DateTime.utc |> Ecto.DateTime.cast!
    query
    |> join(:left, [r], f in assoc(r, :fixtures))
    |> where([r, _], r.id == ^round_.id)
    |> where([_, f], f.starting_at < ^now)
    |> where([_, f], datetime_add(f.starting_at, 2, "hour") > ^now)
    |> select([_, f], f)
end

What I do is the following: starting_at < now < starting_at + 2 "hours"

The result is:

Ecto.Query.CastError at GET /sports/get_all_fixtures
web/models/round.ex:73: value `#Ecto.DateTime<2017-08-02 16:32:29>` in `where` cannot be cast to type :naive_datetime in query:

And if I want to cast as:

    |> where([_, f], datetime_add(f.starting_at, 2, "hour") |> Ecto.DateTime.cast! > ^now)

The result is:

Compiling 11 files (.ex)

== Compilation error in file web/models/round.ex ==
** (Ecto.Query.CompileError) `Ecto.DateTime.cast!(datetime_add(f.starting_at(), 2, "hour"))` is not a valid query expression
    (ecto) expanding macro: Ecto.Query.where/3
    (sopitas) web/models/round.ex:73: Sopitas.Round.fixtures_live/2
    (ecto) expanding macro: Ecto.Query.select/3
    (sopitas) web/models/round.ex:74: Sopitas.Round.fixtures_live/2
    (elixir) expanding macro: Kernel.|>/2
    (sopitas) web/models/round.ex:74: Sopitas.Round.fixtures_live/2
    (elixir) lib/kernel/parallel_compiler.ex:121: anonymous fn/4 in Kernel.ParallelCompiler.spawn_compilers/1

Any ideas?

Upvotes: 0

Views: 1310

Answers (2)

Mike Buhot
Mike Buhot

Reputation: 4885

In addition to Dogbert's answer, you may want to change your schema to use the :naive_datetime or :utc_datetime types in the ecto schema, and use the NaiveDateTime / DateTime modules from the standard library to manipulate the values.

Since Ecto 2.1, the Ecto.DateTime types have been deprecated and looks like they are scheduled to be removed in Ecto 2.2.

Upvotes: 0

Dogbert
Dogbert

Reputation: 222168

datetime_add is defined to return a :naive_datetime. In order to be able to compare it with a value, now should also be a type that can be cast to :naive_datetime. Ecto.DateTime cannot be cast to :naive_datetime, but you can use the new NaiveDateTime module in Elixir.

Just change:

now = Ecto.DateTime.utc |> Ecto.DateTime.cast!

to:

now = NaiveDateTime.utc_now

Upvotes: 1

Related Questions