Конвертировать naive_datetime в utc_datetime_usec - PullRequest
0 голосов
/ 02 мая 2019

У меня есть модель с этой схемой:

schema "my_things" do
    (...)
    field :shifted_inserted_at, :utc_datetime_usec
    timestamps()
  end

timestamps() Тип по умолчанию :naive_datetime.

Мне нужно сместить мое значение inserted_at и вставить его в shifted_inserted_at.

Как преобразовать NaiveDatetime в нужный формат?Я пробовал что-то вроде этого:

  shifted_inserted_at =
    my_thing.inserted_at
    |> DateTime.from_naive!("Etc/UTC")
    |> Timex.shift(days: 10)

  my_thing
  |> Ecto.Changeset.change(shifted_inserted_at: shifted_inserted_at)
  |> Repo.update()

Но я получаю:

** (ArgumentError) :utc_datetime_usec expects microsecond precision, got: #DateTime<2019-05-30 14:40:08Z>

1 Ответ

1 голос
/ 03 мая 2019
Тип

DateTime имеет поле с именем microsecond.Это кортеж, обозначающий значение и точности.

iex|1 ▶ DateTime.from_naive!(
...|1 ▶   ~N[2016-05-24 13:26:08], "Etc/UTC").microsecond       
#⇒ {0, 0}
iex|2 ▶ DateTime.from_naive!(
...|2 ▶   ~N[2016-05-24 13:26:08.123456], "Etc/UTC").microsecond
#⇒ {123456, 6}

Как можно видеть, если действительное значение действительно не имеет микросекунд, точность равна нулю.

Предполагается, чтозначение в базе данных, возвращаемое my_thing.inserted_at , имеет точность микросекунд, можно просто:

~N[2016-05-24 13:26:08.123456]
|> DateTime.from_naive!("Etc/UTC")
|> DateTime.add(10 * 24 * 60 * 60) # 10 × seconds in a day
#⇒ #DateTime<2016-06-03 13:26:08.123456Z>

Если значение не имеет точности микросекунд,

iex|3 ▶ DateTime.from_naive!(~N[2016-05-24 13:26:08], "Etc/UTC")
#        PRECISION ⇒ ZERO!    ⇓⇓⇓ 
#⇒ #DateTime<2016-05-24 13:26:08Z>

можно всегда установить его вручную:

with dt <- DateTime.from_naive!(~N[2016-05-24 13:26:08], "Etc/UTC"),
  do: %DateTime{dt | microsecond: {elem(dt.microsecond, 0), 6}}
#⇒ #DateTime<2016-05-24 13:26:08.000000Z>

Последний теперь может быть вставлен в базу данных.

...