ISO 8601作为Ecto.DateTime.cast()的输入格式

时间:2016-10-17 01:25:43

标签: timestamp elixir ecto

我正在处理来自外部API的数据。它将时间戳返回为ISO 8601格式,带有时区。

我的理解是Ecto版本2.1-rc(我的版本)可以处理这样的时间戳而没有任何问题。但是,当我尝试执行时:

created_at = Ecto.DateTime.cast!("2016-10-16T21:21:27-04:00")

我收到错误:

(Ecto.CastError) cannot cast "2016-10-16T21:21:27-04:00" to datetime

我的时间戳有问题吗?

2 个答案:

答案 0 :(得分:5)

您的时间戳有效ISO 8601但Ecto不支持解析v2.1.0-rc.2的此类日期时间。您可以使用其他库(如timex)来解析它们,转换为UTC,然后将它们存储在Ecto中。

iex(1)> "2016-10-16T21:21:27-04:00" |> Timex.parse!("{ISO:Extended}")
#<DateTime(2016-10-16T21:21:27-04:00 Etc/GMT+4)>
iex(2)> "2016-10-16T21:21:27-04:00" |> Timex.parse!("{ISO:Extended}") |> Timex.to_datetime
#<DateTime(2016-10-17T01:21:27Z Etc/UTC)>

使用Ecto 2.1,您可以将此值直接存储在:utc_datetime字段中:

iex(1)> created_at = "2016-10-16T21:21:27-04:00" |> Timex.parse!("{ISO:Extended}") |> Timex.to_datetime
#<DateTime(2016-10-17T01:21:27Z Etc/UTC)>
iex(2)> Repo.insert!(%Person{created_at: created_at})
12:58:39.959 [debug] QUERY OK db=2.5ms
INSERT INTO "people" ("created_at","inserted_at","updated_at") VALUES ($1,$2,$3) RETURNING "id" [{{2016, 10, 17}, {1, 21, 27, 0}}, {{2016, 10, 17}, {7, 28, 39, 945106}}, {{2016, 10, 17}, {7, 28, 39, 948505}}]
%Friends.Person{__meta__: #Ecto.Schema.Metadata<:loaded, "people">, age: nil,
 created_at: #<DateTime(2016-10-17T01:21:27Z Etc/UTC)>, first_name: nil, id: 1,
 inserted_at: ~N[2016-10-17 07:28:39.945106], last_name: nil,
 updated_at: ~N[2016-10-17 07:28:39.948505]}

答案 1 :(得分:2)

Ecto.DateTime.cast的格式不正确。请在此处查看it

此:

created_at = Ecto.DateTime.cast!("2016-10-16T21:21:27")

不会抛出错误。

在那里禁止使用-。现在,您可以使用其他有效的ISO-8601日期时间,但没有-符号,或者只是跳过它。