Search code examples
elixirphoenix-frameworkecto

How to get difference in years from current date and Ecto.Date instance


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?


Solution

  • 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