Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

* [Ecto.Query] Fix subqueries in interpolated join filters (this changes the representation of `JoinExpr.on` fields to a `BooleanExpr`)
* [Ecto.Query] Fix selecting lists of fields and using `map/2` from subqueries
* [Ecto.Type] Normalize `DateTime` casts to UTC for `:time` and `:time_usec`

## v3.14.2 (2026-08-14)

Expand Down
7 changes: 7 additions & 0 deletions lib/ecto/type.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1114,6 +1114,13 @@ defmodule Ecto.Type do
end
end

defp cast_time(%DateTime{} = datetime) do
case cast_utc_datetime(datetime) do
{:ok, datetime} -> {:ok, DateTime.to_time(datetime)}
:error -> :error
end
end

defp cast_time(%{"hour" => empty, "minute" => empty}) when empty in ["", nil],
do: {:ok, nil}

Expand Down
5 changes: 5 additions & 0 deletions test/ecto/type_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,9 @@ defmodule Ecto.TypeTest do

assert Ecto.Type.cast(:time, ~D[2016-11-11]) ==
:error

assert Ecto.Type.cast(:time, @non_utc_datetime) ==
{:ok, ~T[22:30:07]}
end

test "dump" do
Expand Down Expand Up @@ -607,6 +610,8 @@ defmodule Ecto.TypeTest do
test "cast from DateTime" do
utc_datetime = DateTime.from_naive!(~N[2016-11-11 23:30:10], "Etc/UTC")
assert Ecto.Type.cast(:time_usec, utc_datetime) == {:ok, ~T[23:30:10.000000]}

assert Ecto.Type.cast(:time_usec, @non_utc_datetime) == {:ok, ~T[22:30:07.008000]}
end

test "cast from Date" do
Expand Down
Loading