Eu gostaria de ter a idade de uma pessoa a partir do aniversário. now - birthday / 365
não funciona, porque alguns anos têm 366 dias. Eu vim com o seguinte código:
now = Date.today
year = now.year - birth_date.year
if (date+year.year) > now
year = year - 1
end
Existe uma maneira mais ruby de calcular a idade?
ruby-on-rails
ruby
Mantas
fonte
fonte
Respostas:
Sei que estou atrasado para a festa aqui, mas a resposta aceita quebrará terrivelmente ao tentar descobrir a idade de alguém nascido no dia 29 de fevereiro em um ano bissexto. Isso ocorre porque a chamada para
birthday.to_date.change(:year => now.year)
cria uma data inválida.Eu usei o seguinte código:
fonte
true
||false
?Encontrei esta solução para funcionar bem e ser legível para outras pessoas:
Fácil e você não precisa se preocupar em lidar com o ano bissexto e tal.
fonte
Date.today.month < birthday.month or Date.today.month == birthday.month && Date.today.mday < birthday.mday
.Usa isto:
fonte
rails/activesupport
.Um liner no Ruby on Rails (ActiveSupport). Lida com anos bissextos, segundos bissextos e tudo.
Lógica daqui - Calcular idade em C #
Supondo que as duas datas estejam no mesmo fuso horário, se não ligar
utc()
antesto_s()
em ambas.fonte
(Date.today.to_s(:number).to_i - birthday.to_date.to_s(:number).to_i)/1e4.to_i
também funcionafonte
As respostas até agora são meio estranhas. Sua tentativa original foi bem próxima da maneira correta de fazer isso:
Você obterá um resultado fracionário; sinta-se à vontade para converter o resultado em um número inteiro com
to_i
. Esta é uma solução melhor porque trata corretamente a diferença de data como um período medido em dias (ou segundos no caso da classe Time relacionada) desde o evento. Então, uma divisão simples pelo número de dias em um ano fornece a idade. Ao calcular a idade em anos dessa maneira, contanto que você mantenha o valor original do DOB, não é necessário conceder nenhuma permissão para os anos bissextos.fonte
birthday = DateTime.now - 1.year
dá-me uma idade de 0. Infelizmente, dividir por 365.25 é um pouco impreciso.Minha sugestão:
O truque é que a operação de menos com Time retorna segundos
fonte
Eu gosto deste:
fonte
Esta resposta é a melhor, faça um voto positivo.
Eu gosto da solução do @ philnash, mas o condicional pode ser compactor. O que essa expressão booleana faz é comparar pares [mês, dia] usando ordem lexicográfica , para que você possa usar a comparação de cadeias de ruby:
fonte
(Date.today.strftime('%Y%m%d').to_i - dob.strftime('%Y%m%d').to_i) / 10000
?Esta é uma conversão desta resposta (recebeu muitos votos):
É definitivamente único em sua abordagem, mas faz todo o sentido quando você percebe o que faz:
fonte
Como o Ruby on Rails é marcado, a gema dotiw substitui o distance_of_times_in_words embutido no Rails e fornece o distance_of_times_in_words_hash interno que pode ser usado para determinar a idade. Os anos bissextos são bem tratados para a parte dos anos, embora esteja ciente de que o dia 29 de fevereiro afeta a parte dos dias que justifica o entendimento se esse nível de detalhe é necessário. Além disso, se você não gostar de como o dotiw altera o formato de distance_of_time_in_words, use a opção: vaga para reverter para o formato original.
Adicione dotiw ao Gemfile:
Na linha de comando:
Inclua o DateHelper no modelo apropriado para obter acesso a distance_of_time_in_words e distance_of_time_in_words_hash. Neste exemplo, o modelo é 'Usuário' e o campo de aniversário é 'aniversário.
Adicione este método ao mesmo modelo.
Uso:
fonte
Acredito que isso seja funcionalmente equivalente à resposta do @ philnash, mas o IMO é mais facilmente compreensível.
Uso:
fonte
O seguinte parece funcionar (mas eu apreciaria se estivesse marcado).
fonte
Se você não se importa com um dia ou dois, isso seria mais curto e bastante auto-explicativo.
fonte
Ok, e quanto a isso:
Isso pressupõe que estamos usando trilhos, chamando o
age
método em um modelo, e o modelo possui uma coluna de banco de dados de datasdob
. Isso é diferente de outras respostas, porque esse método usa cadeias para determinar se estamos antes do aniversário deste ano.Por exemplo, se
dob
for 2004/2/28 etoday
for 2014/2/28,age
será2014 - 2004
ou10
. Os carros alegóricos serão0228
e0229
.b4bday
será"0228" < "0229"
outrue
. Finalmente, vamos subtrair1
a partirage
e obter9
.Essa seria a maneira normal de comparar as duas vezes.
Isso funciona da mesma forma, mas a
b4bday
linha é muito longa. O2016
ano também é desnecessário. A comparação de strings no início foi o resultado.Você também pode fazer isso
Se você não estiver usando trilhos, tente isso
👍🏼
fonte
Eu acho que é muito melhor não contar meses, porque você pode obter o dia exato do ano usando
Time.zone.now.yday
.fonte
Criamos uma variação Rails dessa solução
fonte
O DateHelper pode ser usado para obter apenas anos
fonte
fonte
fonte
fonte
Para explicar os anos bissextos (e assumindo a presença do suporte ativo):
years_since
modificará corretamente a data para levar em conta os anos que não são bissextos (quando o aniversário for02-29
).fonte
Aqui está minha solução, que também permite calcular a idade em uma data específica:
fonte
Eu tive que lidar com isso também, mas por meses. Tornou-se muito complicado. A maneira mais simples de pensar era:
Você poderia fazer o mesmo com 12 meses:
Isso usará a classe Date para incrementar o mês, que lidará com 28 dias e ano bissexto etc.
fonte