HTML date tag and :utc_datetime type

Hi,

What transformation is needed to get date input from an HTML date tag in a form to be cast correctly to a :utc_datetime type in a schema?

I have a schema for a calendar event:

schema "events" do
    field :start_date, :utc_datetime
    field :end_date, :utc_datetime
    timestamps()
end

And in my form.html.eex:
<input type="datetime-local">

I came across timex but I do not know where this fits in the changeset, or if this is correct approach. Any guidance most welcomed.

 def changeset(event, attrs) do
    event
    |> cast(attrs, [:start_date, :end_date])
  end

Also, does it matter than I am using :timestampz in my Postgres migration?

create table(:events) do
      add :start_date, :timestamptz
      add :end_date, :timestamptz
end

Thanks!

Going to post a solution to my own question after fumbling around, although I am sure it is the wrong approach :sweat_smile: Any feedback to improve this will be most welcomed!

In my schema, I added two virtual fields to accept form inputs for dates:

  schema "events" do
    field :start_date, :utc_datetime
    field :end_date, :utc_datetime
    field :start_date_input, :string, virtual: true
    field :end_date_input, :string, virtual: true
  end

Then, in my def changeset function I add a function to convert the dates:

  def changeset(event, attrs) do
    event
    |> cast(attrs, [:start_date_input, :end_date_input])
    |> validate_required([start_date_input, :end_date_input])
    |> convert_start_date_to_utc_datetime()
    |> convert_end_date_to_utc_datetime()
  end

Where

  defp convert_start_date_to_utc_datetime(changeset) do
    case fetch_change(changeset, :start_date_input) do
      {:ok, updated_start_date} ->
        put_change(changeset, :start_date, Timex.parse!(updated_start_date, "{ISO:Extended}"))
      :error -> changeset
    end
  end

And similar function for the end_date.

Then, in the controller for edit actions, I convert, using Timex.format, the start_date and end_date to a string and put it back in the Event map as start_date_input and end_date_input respectively, so that it can be viewed in the form.

I’m still learning Elixir and Phoenix, is this approach reasonable?

1 Like