Let's say I have a Person
model and each person has a birthday field set as an Ecto.Date
column.
So if I retrieve a record from the database which represents an instance of this model, what is the best way to get this person's age from his birthday
column?
Not sure about 'best way', but this is a way:
defmodule AgeCalc do
@spec age(Ecto.Date.t, atom|{integer, integer, integer}) :: integer
def age(%Ecto.Date{day: d, month: m, year: y}, as_of \\ :now) do
do_age({y, m, d}, as_of)
end
###########
# Internals
###########
@doc false
def do_age(birthday, :now) do
{today, _time} = :calendar.now_to_datetime(:erlang.now)
calc_diff(birthday, today)
end
def do_age(birthday, date), do: calc_diff(birthday, date)
@doc false
def calc_diff({y1, m1, d1}, {y2, m2, d2}) when m2 > m1 or (m2 == m1 and d2 >= d1) do
y2 - y1
end
def calc_diff({y1,_,_}, {y2,_,_}), do: (y2 - y1) - 1
end
Usage goes like this: (today is September 27th, 2015)
iex(1)> AgeCalc.age(%Ecto.Date{day: 27, month: 9, year: 2000})
15
iex(2)> AgeCalc.age(%Ecto.Date{day: 28, month: 9, year: 2000})
14
or, for a manual calculation against something other than today:
iex(3)> AgeCalc.age(%Ecto.Date{day: 28, month: 9, year: 2000}, {2034, 12, 25})
34