webentwicklung-frage-antwort-db.com.de

Holen Sie sich das Alter der Person in Ruby

Ich möchte das Alter einer Person ab ihrem Geburtstag erhalten. now - birthday / 365 funktioniert nicht, da einige Jahre 366 Tage haben. Ich habe folgenden Code bekommen:

now = Date.today
year = now.year - birth_date.year

if (date+year.year) > now
  year = year - 1
end

Gibt es eine mehr Ruby'ish Methode, um das Alter zu berechnen?

117
Mantas

Ich weiß, ich bin zu spät zur Party hier, aber die akzeptierte Antwort wird schrecklich brechen, wenn man versucht, das Alter einer am 29. Februar in einem Schaltjahr geborenen Person herauszufinden. Dies liegt daran, dass der Aufruf von birthday.to_date.change(:year => now.year) ein ungültiges Datum erstellt.

Ich habe stattdessen den folgenden Code (in einem Rails-Projekt) verwendet:

def age(dob)
  now = Time.now.utc.to_date
  now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)
end
398
philnash

Ich habe festgestellt, dass diese Lösung gut funktioniert und für andere Personen lesbar ist:

    age = Date.today.year - birthday.year
    age -= 1 if Date.today < birthday + age.years #for days before birthday

Einfach und Sie müssen sich keine Sorgen über den Umgang mit dem Schaltjahr und so machen.

48
PJ.

Benutze das: 

def age
  now = Time.now.utc.to_date
  now.year - birthday.year - (birthday.to_date.change(:year => now.year) > now ? 1 : 0)
end
34
Sadegh

Ein Liner in Ruby on Rails (ActiveSupport). Behandelt Schaltjahre, Schaltsekunden und so weiter.

def age(birthday)
  (Time.now.to_s(:number).to_i - birthday.to_time.to_s(:number).to_i)/10e9.to_i
end

Logik von hier - Alter in C # berechnen

Angenommen, beide Datumsangaben liegen in derselben Zeitzone, wenn nicht utc() vor to_s() für beide aufgerufen wird.

16
(Date.today.strftime('%Y%m%d').to_i - dob.strftime('%Y%m%d').to_i) / 10000
9
pguardiario

Mein Vorschlag:

def age(birthday)
    ((Time.now - birthday.to_time)/(60*60*24*365)).floor
end

Der Trick ist, dass der Minus-Vorgang mit der Zeit Sekunden zurückgibt

6
jlebrijo

Die Antworten sind bis jetzt irgendwie komisch. Ihr ursprünglicher Versuch war ziemlich nahe am richtigen Weg, dies zu tun:

birthday = DateTime.new(1900, 1, 1)
age = (DateTime.now - birthday) / 365.25 # or (1.year / 1.day)

Sie erhalten ein unvollständiges Ergebnis. Sie können das Ergebnis also mit to_i in eine Ganzzahl konvertieren. Dies ist eine bessere Lösung, da der Datumsunterschied seit dem Ereignis in Tagen (oder Sekunden im Fall der zugehörigen Zeitklasse) gemessen wird. Dann gibt Ihnen eine einfache Einteilung nach Anzahl der Tage in einem Jahr das Alter. Bei der Berechnung des Alters in Jahren auf diese Weise muss für Schaltjahre keine Vergütung vorgenommen werden, solange Sie den ursprünglichen DOB-Wert beibehalten.

6
Bob Aman

Ich mag das hier: 

now = Date.current
age = now.year - dob.year
age -= 1 if now.yday < dob.yday
4
tpalm

Diese Antwort ist die beste, anstatt sie zu verteidigen.


Ich mag @ philnashs Lösung, aber die Bedingung könnte kompakt sein. Dieser boolesche Ausdruck vergleicht [Monat, Tag] -Paare mit lexikographischer Reihenfolge , so dass man stattdessen einfach Rubys String-Vergleich verwenden kann:

def age(dob)
  now = Date.today
  now.year - dob.year - (now.strftime('%m%d') < dob.strftime('%m%d') ? 1 : 0)
end
4
artm

Dies ist eine Konvertierung von dieser Antwort (es hat viele Stimmen erhalten):

# convert dates to yyyymmdd format
today = (Date.current.year * 100 + Date.current.month) * 100 + Date.today.day
dob = (dob.year * 100 + dob.month) * 100 + dob.day
# NOTE: could also use `.strftime('%Y%m%d').to_i`

# convert to age in years
years_old = (today - dob) / 10000

Es ist definitiv einzigartig in seiner Herangehensweise, macht aber durchaus Sinn, wenn Sie erkennen, was es bewirkt:

today = 20140702 # 2 July 2014

# person born this time last year is a 1 year old
years = (today - 20130702) / 10000

# person born a year ago tomorrow is still only 0 years old
years = (today - 20130703) / 10000

# person born today is 0
years = (today - 20140702) / 10000  # person born today is 0 years old

# person born in a leap year (eg. 1984) comparing with non-leap year
years = (20140228 - 19840229) / 10000 # 29 - a full year hasn't yet elapsed even though some leap year babies think it has, technically this is the last day of the previous year
years = (20140301 - 19840229) / 10000 # 30

# person born in a leap year (eg. 1984) comparing with leap year (eg. 2016)
years = (20160229 - 19840229) / 10000 # 32
2
br3nt

Da Ruby on Rails mit einem Tag versehen ist, überschreibt der dotiw gem das in Rails integrierte distance_of_times_in_words und stellt distance_of_times_in_words_hash zur Verfügung, mit dem das Alter bestimmt werden kann. Sprungjahre werden für den Jahresanteil gut behandelt, obwohl sich der 29. Februar auf den Tagesanteil auswirkt, der ein Verständnis dafür erfordert, ob diese Detailgenauigkeit erforderlich ist. Wenn Sie nicht mögen, wie Dotiw das Format von distance_of_time_in_words ändert, verwenden Sie die Option: vague, um zum ursprünglichen Format zurückzukehren.

Füge dotiw dem Gemfile hinzu:

gem 'dotiw'

In der Kommandozeile:

bundle

Fügen Sie den DateHelper in das entsprechende Modell ein, um Zugriff auf distance_of_time_in_words und distance_of_time_in_words_hash zu erhalten. In diesem Beispiel ist das Modell "Benutzer" und das Geburtstagsfeld ist "Geburtstag".

class User < ActiveRecord::Base
  include ActionView::Helpers::DateHelper

Fügen Sie diese Methode demselben Modell hinzu.

def age
  return nil if self.birthday.nil?
  date_today = Date.today
  age = distance_of_time_in_words_hash(date_today, self.birthday).fetch("years", 0)
  age *= -1 if self.birthday > date_today
  return age
end

Verwendungszweck:

u = User.new("birthday(1i)" => "2011", "birthday(2i)" => "10", "birthday(3i)" => "23")
u.age
1
mindriot

Ich glaube, das ist funktional äquivalent zu @ philnashs Antwort, aber IMO leichter verständlich.

class BirthDate
  def initialize(birth_date)
    @birth_date = birth_date
    @now = Time.now.utc.to_date
  end

  def time_ago_in_years
    if today_is_before_birthday_in_same_year?
      age_based_on_years - 1
    else
      age_based_on_years
    end
  end

  private

  def age_based_on_years
    @now.year - @birth_date.year
  end

  def today_is_before_birthday_in_same_year?
    (@now.month < @birth_date.month) || ((@now.month == @birth_date.month) && (@now.day < @birth_date.day))
  end
end

Verwendungszweck:

> BirthDate.new(Date.parse('1988-02-29')).time_ago_in_years
 => 31 
1
Jason Swett

DateHelper kann nur zum Abrufen von Jahren verwendet werden

puts time_ago_in_words '1999-08-22'

fast 20 Jahre

0
7uthaifah

Ok was ist das hier?

def age
  return unless dob
  t = Date.today
  age = t.year - dob.year
  b4bday = t.strftime('%m%d') < dob.strftime('%m%d')
  age - (b4bday ? 1 : 0)
end

Dies setzt voraus, dass wir Rails verwenden und die Methode age für ein Modell aufrufen, und das Modell hat eine Datumsdatenbankspalte dob. Dies unterscheidet sich von anderen Antworten, da diese Methode anhand von Zeichenfolgen ermittelt, ob wir vor dem diesjährigen Geburtstag sind.

Wenn dob beispielsweise 2004/2/28 und today 2014/2/28 ist, wird age2014 - 2004 oder 10 sein. Die Floats lauten 0228 und 0229. b4bday wird "0228" < "0229" oder true sein. Zum Schluss subtrahieren wir 1 von age und erhalten 9.

Dies wäre der normale Weg, um die beiden Zeiten zu vergleichen.

def age
  return unless dob
  t = Date.today
  age = today.year - dob.year
  b4bday = Date.new(2016, t.month, t.day) < Date.new(2016, dob.month, dob.day)
  age - (b4bday ? 1 : 0)
end

Dies funktioniert genauso, aber die b4bday-Zeile ist zu lang. Das 2016-Jahr ist ebenfalls nicht erforderlich. Der Stringvergleich am Anfang war das Ergebnis.

Sie können das auch tun

Date::DATE_FORMATS[:md] = '%m%d'

def age
  return unless dob
  t = Date.today
  age = t.year - dob.year
  b4bday = t.to_s(:md) < dob.to_s(:md)
  age - (b4bday ? 1 : 0)
end

Wenn Sie Rails nicht verwenden, versuchen Sie dies

def age(dob)
  t = Time.now
  age = t.year - dob.year
  b4bday = t.strftime('%m%d') < dob.strftime('%m%d')
  age - (b4bday ? 1 : 0)
end

????????

0
Cruz Nunez

Ich denke, es ist viel besser, Monate nicht zu zählen, weil man mit Time.zone.now.yday den genauen Tag eines Jahres ermitteln kann.

def age
  years  = Time.zone.now.year - birthday.year
  y_days = Time.zone.now.yday - birthday.yday

  y_days < 0 ? years - 1 : years
end
0
Oleksiy Nosov

Kam mit einer Rails-Variante dieser Lösung auf

def age(dob)
    now = Date.today
    age = now.year - dob.year
    age -= 1 if dob > now.years_ago(age)
    age
end
0
derosm2

Wenn Sie sich nicht für ein oder zwei Tage interessieren, wäre dies kürzer und ziemlich selbsterklärend.

(Time.now - Time.gm(1986, 1, 27).to_i).year - 1970
0
hakunin

Das folgende scheint zu funktionieren (aber ich würde es zu schätzen wissen, wenn es überprüft wurde).

age = now.year - bday.year
age -= 1 if now.to_a[7] < bday.to_a[7]
0
testr