# Calculate age based on DoB

**URL:** <https://www.ruby-forum.com/t/calculate-age-based-on-dob/50575>\
**Category:** Rails\
**Created:** [December 18, 2005, 12:24pm UTC](https://www.ruby-forum.com/t/calculate-age-based-on-dob/50575 "2005-12-18T12:24:32Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![jeroen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/bbe5ce/32.png) [@jeroen](https://www.ruby-forum.com/u/jeroen)\
**Post date:** [December 18, 2005, 12:24pm UTC](https://www.ruby-forum.com/t/calculate-age-based-on-dob/50575/1 "2005-12-18T12:24:32Z")

</div>

Hi,

I wrote a little helper that calulates someone’s age based on his/her  
date of birth.

def age(dob)  
diff = Date.today - dob  
age = (diff / 365.25).floor  
age.to\_s  
end

It works fine, but it’s not completely accurate as it just takes the  
average days in a year. It should be able to calculate this more  
accurately, right? I can’t work it out though…

Jeroen

---

<div class="post-metadata">

**Author:** ![jeroen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/bbe5ce/32.png) [@jeroen](https://www.ruby-forum.com/u/jeroen)\
**Post date:** [December 18, 2005, 3:13pm UTC](https://www.ruby-forum.com/t/calculate-age-based-on-dob/50575/2 "2005-12-18T15:13:17Z")

</div>

Jeroen H. wrote:

> Hi,
> 
> I wrote a little helper that calulates someone’s age based on his/her  
> date of birth.
> 
> def age(dob)  
> diff = Date.today - dob  
> age = (diff / 365.25).floor  
> age.to\_s  
> end
> 
> It works fine, but it’s not completely accurate as it just takes the  
> average days in a year. It should be able to calculate this more  
> accurately, right? I can’t work it out though…
> 
> Jeroen

Give this a try Jeroen:

def get\_age(dob)  
return nil unless dob  
now = Time.now  
now.year - dob.year - (dob.to\_time.change(:year =\> now.year) \> now ? 1  
: 0)  
end

---

<div class="post-metadata">

**Author:** ![jeroen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/bbe5ce/32.png) [@jeroen](https://www.ruby-forum.com/u/jeroen)\
**Post date:** [December 18, 2005, 4:06pm UTC](https://www.ruby-forum.com/t/calculate-age-based-on-dob/50575/3 "2005-12-18T16:06:57Z")

</div>

> > > now.year - dob.year - (dob.to\_time.change(:year =\> now.year) \> now ?  
> > > 1

Nifty. It can’t handle dobs before 1970 though.

---

<div class="post-metadata">

**Author:** ![jeroen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/bbe5ce/32.png) [@jeroen](https://www.ruby-forum.com/u/jeroen)\
**Post date:** [December 18, 2005, 4:12pm UTC](https://www.ruby-forum.com/t/calculate-age-based-on-dob/50575/4 "2005-12-18T16:12:58Z")

</div>

Here’s one that’s not optimized in any way, but it is accurate:

def age(dob)  
unless dob.nil?  
a = Date.today.year - dob.year  
b = Date.new(Date.today.year, dob.month, dob.day)  
a = a-1 if b \> Date.today  
return a  
end  
nil  
end

---

<div class="post-metadata">

**Author:** ![jeroen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/bbe5ce/32.png) [@jeroen](https://www.ruby-forum.com/u/jeroen)\
**Post date:** [December 18, 2005, 4:37pm UTC](https://www.ruby-forum.com/t/calculate-age-based-on-dob/50575/5 "2005-12-18T16:37:06Z")

</div>

> > Here’s one that’s not optimized in any way, but it is accurate:

Good but fails on leap days.

d = Date.new(2000,2,29)  
age(d) #throws exception

---

<div class="post-metadata">

**Author:** ![jeroen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/bbe5ce/32.png) [@jeroen](https://www.ruby-forum.com/u/jeroen)\
**Post date:** [December 19, 2005, 3:48am UTC](https://www.ruby-forum.com/t/calculate-age-based-on-dob/50575/6 "2005-12-19T03:48:00Z")

</div>

Sean S. wrote:

> Ouch. Okay so does anyone have a method for turning a date object into  
> an age which works for both dates before 1970 and leap days?

Here’s one for Brian to test:

def age\_at(date, dob)  
day\_diff = date.day - dob.day  
month\_diff = date.month - dob.month - (day\_diff \< 0 ? 1 : 0)  
date.year - dob.year - (month\_diff \< 0 ? 1 : 0)  
end

Both arguments must be Dates.

regards

Justin

---

<div class="post-metadata">

**Author:** ![jeroen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/bbe5ce/32.png) [@jeroen](https://www.ruby-forum.com/u/jeroen)\
**Post date:** [December 19, 2005, 12:43am UTC](https://www.ruby-forum.com/t/calculate-age-based-on-dob/50575/7 "2005-12-19T00:43:58Z")

</div>

Brian B. wrote:

> > > Here’s one that’s not optimized in any way, but it is accurate:
> 
> Good but fails on leap days.
> 
> d = Date.new(2000,2,29)  
> age(d) #throws exception

Ouch. Okay so does anyone have a method for turning a date object into  
an age which works for both dates before 1970 and leap days?

---

<div class="post-metadata">

**Author:** ![jeroen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/bbe5ce/32.png) [@jeroen](https://www.ruby-forum.com/u/jeroen)\
**Post date:** [December 19, 2005, 10:10am UTC](https://www.ruby-forum.com/t/calculate-age-based-on-dob/50575/8 "2005-12-19T10:10:38Z")

</div>

Justin F. wrote:

> > > d = Date.new(2000,2,29)  
> > > def age\_at(date, dob)  
> > > day\_diff = date.day - dob.day  
> > > month\_diff = date.month - dob.month - (day\_diff \< 0 ? 1 : 0)  
> > > date.year - dob.year - (month\_diff \< 0 ? 1 : 0)  
> > > end
> 
> Both arguments must be Dates.

Works fine for me. Also handles pre 1970 dates just fine.  
Thanks!

Jeroen

---

<div class="post-metadata">

**Author:** ![jeroen](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/bbe5ce/32.png) [@jeroen](https://www.ruby-forum.com/u/jeroen)\
**Post date:** [December 19, 2005, 3:50pm UTC](https://www.ruby-forum.com/t/calculate-age-based-on-dob/50575/9 "2005-12-19T15:50:38Z")

</div>

What about this?

def age(dob)  
unless dob.nil?  
years = Date.today.year - dob.year  
if Date.today.month \< dob.month  
years = years + 1  
end  
if (Date.today.month == dob.month and  
Date.today.day \< dob.day)  
years = years - 1  
end  
return years  
end  
nil  
end

Frank
