我想知道一个人的生日。now - birthday / 365
不起作用,因为有些年份有366天。我想出了以下代码:
now = Date.today
year = now.year - birth_date.year
if (date+year.year) > now
year = year - 1
end
还有更Ruby的方法来计算年龄吗?
我想知道一个人的生日。now - birthday / 365
不起作用,因为有些年份有366天。我想出了以下代码:
now = Date.today
year = now.year - birth_date.year
if (date+year.year) > now
year = year - 1
end
还有更Ruby的方法来计算年龄吗?
Answers:
我知道我在这里参加聚会迟到了,但是当尝试计算February年2月29日出生的人的年龄时,公认的答案将令人震惊。这是因为呼叫会birthday.to_date.change(:year => now.year)
建立无效的日期。
我改用以下代码:
require 'date'
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
true
|| false
?
我发现此解决方案很好用,并且对其他人可读:
age = Date.today.year - birthday.year
age -= 1 if Date.today < birthday + age.years #for days before birthday
简单易行,您无需担心如何处理leap年。
Date.today.month < birthday.month or Date.today.month == birthday.month && Date.today.mday < birthday.mday
。
用这个:
def age
now = Time.now.utc.to_date
now.year - birthday.year - (birthday.to_date.change(:year => now.year) > now ? 1 : 0)
end
rails/activesupport
。
Ruby on Rails(ActiveSupport)中的一个内衬。处理leap年,leap秒等等。
def age(birthday)
(Time.now.to_s(:number).to_i - birthday.to_time.to_s(:number).to_i)/10e9.to_i
end
从这里开始的逻辑- 用C#计算年龄
假设两个日期都在相同的时区,如果两个日期utc()
之前都未调用过to_s()
。
(Date.today.to_s(:number).to_i - birthday.to_date.to_s(:number).to_i)/1e4.to_i
也有效
(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
。这是一个更好的解决方案,因为它可以将日期差正确地视为自事件发生以来以天(或秒,在相关的Time类中为秒)度量的时间段。然后简单地除以一年中的天数即可得出年龄。以这种方式计算年龄时,只要保留原始的DOB值,就无需为leap年做任何准备。
birthday = DateTime.now - 1.year
给我一个0岁的年龄。不幸的是,除以365.25有点不精确。
我喜欢这一个:
now = Date.current
age = now.year - dob.year
age -= 1 if now.yday < dob.yday
这个答案是最好的,请赞成。
我喜欢@philnash的解决方案,但条件可以更紧凑。布尔表达式的作用是使用字典顺序比较[month,day]对,因此可以只使用ruby的字符串比较:
def age(dob)
now = Date.today
now.year - dob.year - (now.strftime('%m%d') < dob.strftime('%m%d') ? 1 : 0)
end
(Date.today.strftime('%Y%m%d').to_i - dob.strftime('%Y%m%d').to_i) / 10000
呢
这是此答案的转换(获得了很多票):
# 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日确实会对天数部分产生影响,但请务必了解understanding年部分的fine年,以便了解是否需要该详细程度。另外,如果您不喜欢dotiw如何更改distance_of_time_in_words的格式,请使用:vague选项恢复为原始格式。
将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
我相信这在功能上等同于@philnash的答案,但IMO更容易理解。
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
用法:
> BirthDate.new(Date.parse('1988-02-29')).time_ago_in_years
=> 31
好吧,这呢:
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数据库column dob
。这与其他答案不同,因为此方法使用字符串来确定我们是否在今年的生日之前。
例如,如果dob
是2004/2/28和2014/2/28 today
,age
则将是2014 - 2004
或10
。浮点数将为0228
和0229
。b4bday
将是"0228" < "0229"
或true
。最后,我们将减去1
从age
和获得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
年也是不必要的。开头的字符串比较就是结果。
您也可以这样做
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
如果您不使用滑轨,请尝试以下操作
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
。
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 computed_age
if birth_date.present?
current_time.year - birth_date.year - (age_by_bday || check_if_newborn ? 0 : 1)
else
age.presence || 0
end
end
private
def current_time
Time.now.utc.to_date
end
def age_by_bday
current_time.month > birth_date.month
end
def check_if_newborn
(current_time.month == birth_date.month && current_time.day >= birth_date.day)
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
要考虑leap年(并假设存在主动支持):
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
将正确修改日期以考虑非-年(生日为02-29
)。
这是我的解决方案,它还允许计算特定日期的年龄:
def age on = Date.today
(_ = on.year - birthday.year) - (on < birthday.since(_.years) ? 1 : 0)
end
我也不得不处理这个问题,但是几个月了。变得太复杂了。我能想到的最简单的方法是:
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天和leap年等。