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?
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
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.
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
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.
(Date.today.strftime('%Y%m%d').to_i - dob.strftime('%Y%m%d').to_i) / 10000
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
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.
Ich mag das hier:
now = Date.current
age = now.year - dob.year
age -= 1 if now.yday < dob.yday
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
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
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
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
DateHelper kann nur zum Abrufen von Jahren verwendet werden
puts time_ago_in_words '1999-08-22'
fast 20 Jahre
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 age
2014 - 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
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
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
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
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]