1 Вопрос: Конвертировать naive_datetime в utc_datetime_usec

вопрос создан в Thu, May 2, 2019 12:00 AM

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

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>
    
0
1 ответ                              1                         

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>

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

    
1
2019-05-03 04: 41: 49Z
  1. У
    my_thing.inserted_at не было микросекунд, поэтому мне пришлось перейти на второй путь. Это сработало без нареканий. Спасибо
    2019-05-03 07: 41: 55Z
источник размещен Вот