3

假设我有一个Person模型,每个人都有一个生日字段设置为一Ecto.Date列。

birthday因此,如果我从数据库中检索代表此模型实例的记录,那么从他的列中获取此人年龄的最佳方法是什么?

4

4 回答 4

3

不确定“最佳方式”,但这是一种方式:

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

用法是这样的:(今天是 2015 年 9 月 27 日)

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

或者,对于今天以外的其他内容进行手动计算:

iex(3)> AgeCalc.age(%Ecto.Date{day: 28, month: 9, year: 2000}, {2034, 12, 25})
34
于 2015-09-27T13:42:37.470 回答
1

我使用fragmentEcto 的查询 API。我有一个带有生日列的用户表,并且正在使用以下查询:

Repo.all(from u in User, select: fragment("age(?)", u.birthday))

查询返回%Postgrex.Interval{}带有字段daysmonthssecs的 。需要几个月和div12 岁才能得到年龄。

我喜欢 Timex,但使用 Postgres 的本机age功能对我来说似乎更干净、更快捷。

于 2019-04-08T13:14:49.007 回答
1

我像这样在长生不老药中做到了

  def calculate_age(dob) when is_binary(dob)
  def calculate_age(dob) when is_binary(dob) do
    today = Date.utc_today()
    dob = Date.from_iso8601! dob
    today.year - dob.year
  end
于 2019-12-19T19:08:44.313 回答
0

我知道这有点旧,但我只是遇到了这个并编写了我自己的函数,我认为它更容易理解,使用Date来自 Elixir ,它已经被替换 Ecto.Date

def get_person_age(%Person{} = person) do
  today = Date.utc_today()
  {:ok, today_in_birthday_year} = Date.new(person.birthday.year, today.month, today.day)
  years_diff = today.year - person.birthday.year

  if Date.compare(today_in_birthday_year, person.birthday) == :lt do
    years_diff - 1
  else
    years_diff
  end
end
于 2022-02-09T02:43:49.807 回答