Skip to content

Commit

Permalink
Fix datetime serialization format via :datetime_type config
Browse files Browse the repository at this point in the history
Thank you @krwenholz for pointing this out.

closes: #116
  • Loading branch information
warmwaffles committed Sep 5, 2024
1 parent 826b052 commit 83d4a32
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ The format is loosely based on [Keep a Changelog][keepachangelog], and this
project adheres to [Semantic Versioning][semver].

## Unreleased
- fixed: Handle datetime serialization format via `:datetime_type` config.

## v0.17.1
- changed: Bump minimum ecto to `3.12`.
Expand Down
8 changes: 6 additions & 2 deletions lib/ecto/adapters/sqlite3/codec.ex
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,16 @@ defmodule Ecto.Adapters.SQLite3.Codec do
end

@text_datetime_format "%Y-%m-%d %H:%M:%S"
@iso8601_format "%Y-%m-%dT%H:%M:%S"

def datetime_format(:text_datetime), do: @text_datetime_format
def datetime_format(_), do: @iso8601_format

def utc_datetime_encode(nil, :iso8601), do: {:ok, nil}
def utc_datetime_encode(nil, :text_datetime), do: {:ok, nil}

def utc_datetime_encode(%{time_zone: "Etc/UTC"} = value, :iso8601) do
{:ok, NaiveDateTime.to_iso8601(value)}
{:ok, Calendar.strftime(value, @iso8601_format)}
end

def utc_datetime_encode(%{time_zone: "Etc/UTC"} = value, :text_datetime) do
Expand All @@ -135,7 +139,7 @@ defmodule Ecto.Adapters.SQLite3.Codec do
def naive_datetime_encode(nil, :text_datetime), do: {:ok, nil}

def naive_datetime_encode(value, :iso8601) do
{:ok, NaiveDateTime.to_iso8601(value)}
{:ok, Calendar.strftime(value, @iso8601_format)}
end

def naive_datetime_encode(value, :text_datetime) do
Expand Down
6 changes: 5 additions & 1 deletion lib/ecto/adapters/sqlite3/connection.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1369,10 +1369,14 @@ defmodule Ecto.Adapters.SQLite3.Connection do
[quote_name(name)]
end

@datetime_type Application.compile_env(:ecto_sqlite3, :datetime_type, :iso8601)

defp expr({:datetime_add, _, [datetime, count, interval]}, sources, query) do
format = Ecto.Adapters.SQLite3.Codec.datetime_format(@datetime_type)

[
"CAST (",
"strftime('%Y-%m-%d %H:%M:%f000Z'",
"strftime('#{format}'",
",",
expr(datetime, sources, query),
",",
Expand Down
4 changes: 2 additions & 2 deletions test/ecto/adapters/sqlite3/connection/datetime_add_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ defmodule Ecto.Adapters.SQLite3.Connection.DatetimeAddTest do
|> select([], true)
|> plan()

assert ~s{SELECT 1 FROM "schema" AS s0 WHERE (CAST (strftime('%Y-%m-%d %H:%M:%f000Z',s0.\"foo\",1 || ' month') AS TEXT) > s0."bar")} ==
assert ~s{SELECT 1 FROM "schema" AS s0 WHERE (CAST (strftime('%Y-%m-%dT%H:%M:%S',s0.\"foo\",1 || ' month') AS TEXT) > s0."bar")} ==
all(query)
end

Expand All @@ -22,7 +22,7 @@ defmodule Ecto.Adapters.SQLite3.Connection.DatetimeAddTest do
|> select([], true)
|> plan()

assert ~s{SELECT 1 FROM "schema" AS s0 WHERE (CAST (strftime('%Y-%m-%d %H:%M:%f000Z',CAST(s0.\"foo\" AS TEXT),1 || ' month') AS TEXT) > s0."bar")} ==
assert ~s{SELECT 1 FROM "schema" AS s0 WHERE (CAST (strftime('%Y-%m-%dT%H:%M:%S',CAST(s0.\"foo\" AS TEXT),1 || ' month') AS TEXT) > s0."bar")} ==
all(query)
end
end
30 changes: 30 additions & 0 deletions test/ecto/integration/timestamps_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,31 @@ defmodule Ecto.Integration.TimestampsTest do
|> TestRepo.all()
end

test "using built in ecto functions" do
account = insert_account(%{name: "Test"})

insert_product(%{
account_id: account.id,
name: "Foo",
inserted_at: seconds_ago(1)
})

insert_product(%{
account_id: account.id,
name: "Bar",
inserted_at: seconds_ago(3)
})

assert [
%{name: "Foo"},
] =
Product
|> select([p], p)
|> where([p], p.inserted_at >= ago(2, "second"))
|> order_by([p], desc: p.inserted_at)
|> TestRepo.all()
end

defp insert_account(attrs) do
%Account{}
|> Account.changeset(attrs)
Expand All @@ -192,4 +217,9 @@ defmodule Ecto.Integration.TimestampsTest do
|> Product.changeset(attrs)
|> TestRepo.insert!()
end

defp seconds_ago(seconds) do
now = DateTime.utc_now()
DateTime.add(now, -seconds, :second)
end
end

0 comments on commit 83d4a32

Please sign in to comment.