diff --git a/apps/alchemist/mix.exs b/apps/alchemist/mix.exs index 3f01515d2..4e74e2379 100644 --- a/apps/alchemist/mix.exs +++ b/apps/alchemist/mix.exs @@ -4,7 +4,7 @@ defmodule Alchemist.MixProject do def project do [ app: :alchemist, - version: "0.2.27", + version: "0.2.28", elixir: "~> 1.10", build_path: "../../_build", config_path: "../../config/config.exs", diff --git a/apps/transformers/lib/transformations/date_time.ex b/apps/transformers/lib/transformations/date_time.ex index df745b6ec..c2d575dc3 100644 --- a/apps/transformers/lib/transformations/date_time.ex +++ b/apps/transformers/lib/transformations/date_time.ex @@ -1,6 +1,8 @@ defmodule Transformers.DateTime do @behaviour Transformation + use Timex + alias Transformers.FieldFetcher alias Transformers.Validations.DateTimeFormat alias Transformers.Validations.NotBlank @@ -51,7 +53,7 @@ defmodule Transformers.DateTime do end defp string_to_datetime(date_string, date_format, source_field) do - with {:ok, result} <- Timex.parse(date_string, date_format) do + with {:ok, result} <- parse_format(date_string, date_format) do {:ok, result} else {:error, timexReason} -> @@ -62,6 +64,23 @@ defmodule Transformers.DateTime do end end + defp parse_format(string, format) do + if format == "{s-epoch}" do + try do + seconds = + if String.contains?(string, "."), + do: trunc(String.to_float(string)), + else: String.to_integer(string) + + {:ok, Timex.from_unix(seconds)} + rescue + err -> {:error, err.message} + end + else + Timex.parse(string, format) + end + end + defp format_datetime(dateTime, format) do with {:ok, result} <- Timex.format(dateTime, format) do {:ok, result} diff --git a/apps/transformers/mix.exs b/apps/transformers/mix.exs index 8b41f684c..e37409bc8 100644 --- a/apps/transformers/mix.exs +++ b/apps/transformers/mix.exs @@ -4,7 +4,7 @@ defmodule Transformers.MixProject do def project do [ app: :transformers, - version: "1.0.22", + version: "1.0.23", build_path: "../../_build", config_path: "../../config/config.exs", deps_path: "../../deps", diff --git a/apps/transformers/test/unit/transformations/date_time_test.exs b/apps/transformers/test/unit/transformations/date_time_test.exs index 1a258c45a..bcb26002c 100644 --- a/apps/transformers/test/unit/transformations/date_time_test.exs +++ b/apps/transformers/test/unit/transformations/date_time_test.exs @@ -20,6 +20,54 @@ defmodule Transformers.DateTimeTest do assert actual_transformed_field == "February 28, 2022 4:53 PM" end + test "parses time since epoch" do + params = %{ + "sourceField" => "date1", + "targetField" => "date2", + "sourceFormat" => "{s-epoch}", + "targetFormat" => "{ISOdate}" + } + + message_payload = %{"date1" => "1681232228"} + + {:ok, transformed_payload} = Transformers.DateTime.transform(message_payload, params) + + {:ok, actual_transformed_field} = Map.fetch(transformed_payload, params["targetField"]) + assert actual_transformed_field == "2023-04-11" + end + + test "parses epoch time and truncates decimal values" do + params = %{ + "sourceField" => "date1", + "targetField" => "date2", + "sourceFormat" => "{s-epoch}", + "targetFormat" => "{Mfull} {D}, {YYYY} {h12}:{m} {AM}" + } + + message_payload = %{"date1" => "1681232228.33823"} + + {:ok, transformed_payload} = Transformers.DateTime.transform(message_payload, params) + + {:ok, actual_transformed_field} = Map.fetch(transformed_payload, params["targetField"]) + assert actual_transformed_field == "April 11, 2023 4:57 PM" + end + + test "converts to epoch" do + params = %{ + "sourceField" => "date1", + "targetField" => "date2", + "sourceFormat" => "{YYYY}-{0M}-{D} {h24}:{m}", + "targetFormat" => "{s-epoch}" + } + + message_payload = %{"date1" => "2022-02-28 16:53"} + + {:ok, transformed_payload} = Transformers.DateTime.transform(message_payload, params) + + {:ok, actual_transformed_field} = Map.fetch(transformed_payload, params["targetField"]) + assert actual_transformed_field == "1646067180" + end + test "when source and target are the same field, source is overwritten" do params = %{ "sourceField" => "date1", @@ -124,6 +172,22 @@ defmodule Transformers.DateTimeTest do "Unable to parse datetime from \"date1\" in format \"{YYYY}-{0M}-{D} {h24}:{m}\": Expected `2 digit month` at line 1, column 4." end + test "returns error when epoch is incorrect" do + params = %{ + "sourceField" => "date1", + "targetField" => "date2", + "sourceFormat" => "{s-epoch}", + "targetFormat" => "{ISOdate}" + } + + message_payload = %{"date1" => "epoch"} + + {:error, reason} = Transformers.DateTime.transform(message_payload, params) + + assert reason == + "Unable to parse datetime from \"date1\" in format \"{s-epoch}\": argument error" + end + test "performs transform as normal when condition evaluates to true" do params = %{ "sourceField" => "date1", @@ -177,7 +241,7 @@ defmodule Transformers.DateTimeTest do parameters = %{ "sourceField" => "date1", "targetField" => "date2", - "sourceFormat" => "{YYYY}-{0M}-{D} {h24}:{m}", + "sourceFormat" => "{s-epoch}", "targetFormat" => "{Mfull} {D}, {YYYY} {h12}:{m} {AM}" }