This is another part of my series on learning Elixir.
In the previous episode, I calculated the distance of flight. I will use it later for gathering statistics. Another metric, I would like to have is a time of flight. Usually, flight departure and arrival times are presented in local time. So it gets a bit tricky to get the time length when the journey spans across few time zones.
Elixir’s standard DateTime library doesn’t work with time zones very well. The Internet suggests I should use Timex.
But first I needed to make some changes into my database because up until now, I had only flight date. A few weeks ago I wrote a post, how to update your schema with migrations and this time I followed the same steps. Still, I haven’t figure out how to do it in a bit more automated manner.
defmodule Flightlog.Repo.Migrations.CreateFlight do use Ecto.Migration def change do alter table(:flights) do modify :arrival_date, Timex.Ecto.DateTimeWithTimezone modify :departure_date, Timex.Ecto.DateTimeWithTimezone end end end
As you can see, I used specific Timex types. This works only with Postgre, and if you want to use timezones it needs one additional step. You’ll have to add custom type to your database:
CREATE TYPE datetimetz AS ( dt timestamptz, tz varchar );
You can read more about using Timex with Ecto on this documentation page.
I also updated my flight.ex
model. It looks like that right now:
defmodule Flightlog.Flight do use Flightlog.Web, :model schema "flights" do field :departure_date, Timex.Ecto.DateTimeWithTimezone field :arrival_date, Timex.Ecto.DateTimeWithTimezone field :flight_number, :string field :plane_type, :string field :from, :string field :to, :string timestamps() end @doc """ Builds a changeset based on the `struct` and `params`. """ def changeset(struct, params \\ %{}) do struct |> cast(params, [:departure_date, :arrival_date, :flight_number, :plane_type, :from, :to]) |> validate_required([:departure_date, :arrival_date, :flight_number, :plane_type, :from, :to]) end end
After that, I walked along the path that’s proven to work in the flight distance part. I added a new function in my math.ex
library, making use of Timex diff function:
def flightTime(earlier, later) do hours = Timex.diff(later, earlier, :hours) minutes = rem(Timex.diff(later, earlier, :minutes), 60) "#{hours}:#{minutes}" end
And I’m calling it from the view in another function, so it’s easily accessible from the template:
def time(time1, time2) do Flightlog.Math.flightTime(time1, time2) end
And that was it. Although it took me few hours because I was struggling a bit with Timex types. I didn’t read carefully the documentation and for example missed the step with creating new Postgre type. Good lesson here, to look into docs carefully :)
The effect:
As you can see, I made some approach at formatting dates. Unfortunately, I didn’t manage to show them in local time. They’re in UTC in here. This will be next step most likely.
That’s all for today. Next week we’ll try to test this new module. In the meantime, check previous episodes. And if you’re interested in machine learning, look into my weekly link drop.