在Ruby中获取人的年龄
我想从生日那天就得到一个人的年龄。 now - birthday / 365
不工作,因为有些年份有366天。 我想出了以下代码:
now = Date.today year = now.year - birth_date.year if (date+year.year) > now year = year - 1 end
有更多的Ruby'ish方式来计算年龄?
我知道我在这里参加晚会的时间已经很晚了,但是在试图计算一个闰年出生在二月二十九日的人的年龄的时候,接受的答案将会大打折扣。 这是因为对birthday.to_date.change(:year => now.year)
的调用会创build一个无效的date。
我使用了下面的代码(在Rails项目中):
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
我发现这个解决scheme能够很好地工作,对其他人可读:
age = Date.today.year - birthday.year age -= 1 if Date.today < birthday + age.years #for days before birthday
容易,你不必担心处理闰年等。
用这个:
def age now = Time.now.utc.to_date now.year - birthday.year - (birthday.to_date.change(:year => now.year) > now ? 1 : 0) end
Ruby on Rails中的一个class轮(ActiveSupport)。 处理闰年,闰秒等。
def age(birthday) (Time.now.to_s(:number).to_i - birthday.to_time.to_s(:number).to_i)/10e9.to_i end
从这里开始的逻辑 – 用C#计算年龄
假设两个date都在同一时区,如果两者都不在to_s()
之前调用utc()
。
(Date.today.strftime('%Y%m%d').to_i - dob.strftime('%Y%m%d').to_i) / 10000
迄今为止的答案有点奇怪。 你最初的尝试是非常接近正确的方式来做到这一点:
birthday = DateTime.new(1900, 1, 1) age = (DateTime.now - birthday) / 365.25 # or (1.year / 1.day)
您将得到一个小数结果,所以随意将结果转换为与to_i
的整数。 这是一个更好的解决scheme,因为它将date差别正确地视为以天为单位的时间段(或者在相关时间类的情况下的秒数)。 然后按照一年中的天数来简单的划分你的年龄。 以这种方式计算年龄时,只要保留原来的DOB值,闰年就不需要补贴。
我喜欢这一个:
now = Date.current age = now.year - dob.year age -= 1 if now.yday < dob.yday
我的build议:
def age(birthday) ((Time.now - birthday.to_time)/(60*60*24*365)).floor end
诀窍是,时间的减号操作返回秒
这个答案是最好的,反而upvote。
我喜欢@ philnash的解决scheme,但条件可能是compacter。 布尔expression式所做的是使用字典顺序来比较[month,day]对,所以可以使用ruby的string比较来代替:
def age(dob) now = Date.today now.year - dob.year - (now.strftime('%m%d') < dob.strftime('%m%d') ? 1 : 0) end
这是这个答案的转换(它收到了很多票):
# 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
它的方法绝对是独一无二的,但是当你意识到它的作用时,它是非常有意义的:
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
由于Ruby on Rails被标记,所以dotiw gem覆盖了Rails内置的distance_of_times_in_words,并提供了可用于确定年龄的distance_of_times_in_words_hash 。 闰年多年来处理得很好,但要注意,如果需要这个详细程度的话,2月29日对于需要理解的日子部分有影响。 此外,如果您不喜欢dotiw如何更改distance_of_time_in_words的格式,请使用:模糊选项恢复为原始格式。
添加dotiw到Gemfile:
gem 'dotiw'
在命令行上:
bundle
将DateHelper包含在适当的模型中以获得对distance_of_time_in_words和distance_of_time_in_words_hash的访问权限。 在这个例子中,模型是“用户”,生日字段是“生日”。
class User < ActiveRecord::Base include ActionView::Helpers::DateHelper
将此方法添加到相同的模型。
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
用法:
u = User.new("birthday(1i)" => "2011", "birthday(2i)" => "10", "birthday(3i)" => "23") u.age
以下似乎工作(但我会很感激,如果它被检查)。
age = now.year - bday.year age -= 1 if now.to_a[7] < bday.to_a[7]
如果你不关心一两天,这将是更短,相当自我解释。
(Time.now - Time.gm(1986, 1, 27).to_i).year - 1970
好的,这个怎么样:
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
这是假设我们正在使用rails,在模型上调用age
方法,并且该模型具有date数据库列dob
。 这与其他答案不同,因为此方法使用string来确定我们是否在今年的生日之前。
例如,如果dob
是2004/2/28,而today
是2014/2/28,那么age
将是2014 - 2004
或10
。 花车将是0228
和0229
。 b4bday
将为"0228" < "0229"
或true
。 最后,我们将从age
减1
,得到9
。
这将是两次比较的正常方式。
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
这工作是一样的,但是b4bday
线太长了。 2016
年也是不必要的。 开始的string比较是结果。
你也可以做到这一点
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
如果你不使用rails,试试这个
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
👍🏼
我觉得不要数数月,因为你可以通过使用Time.zone.now.yday
得到一年中的Time.zone.now.yday
。
def age years = Time.zone.now.year - birthday.year y_days = Time.zone.now.yday - birthday.yday y_days < 0 ? years - 1 : years end
def birthday(user) today = Date.today new = user.birthday.to_date.change(:year => today.year) user = user.birthday if Date.civil_to_jd(today.year, today.month, today.day) >= Date.civil_to_jd(new.year, new.month, new.day) age = today.year - user.year else age = (today.year - user.year) -1 end age end
Time.now.year - self.birthdate.year - (birthdate.to_date.change(:year => Time.now.year) > Time.now.to_date ? 1 : 0)
考虑闰年(并假设有效的支持):
def age return unless birthday now = Time.now.utc.to_date years = now.year - birthday.year years - (birthday.years_since(years) > now ? 1 : 0) end
years_since
将正确修改date以考虑非闰年(当生日是02-29
)。
我也必须处理这个,但几个月。 变得太复杂了。 我能想到的最简单的方法是:
def month_number(today = Date.today) n = 0 while (dob >> n+1) <= today n += 1 end n end
你可以在12个月内做同样的事情:
def age(today = Date.today) n = 0 while (dob >> n+12) <= today n += 1 end n end
这将使用Date类来增加月份,这将处理28天和闰年等。