  Deriving Age from Date of Birth, Allowing for Leap Years

First the Basics

I guess it’s a common mistake, especially for those new to database work, to store the Age of a person in a database table.

Of course, the main reason that this is a bad idea is that age changes, so keeping the stored data accurate in such a case becomes a near impossibility.

The usual advice, therefore, is to store the Date of Birth (which does not vary), and calculate the Age whenever it is required for the purposes of the database application.

A Common Expression

A search of the internet, newsgroups, etc. will reveal plenty of different approaches to calculating Age, based on Date of Birth.  Some are more accurate than others.

A commonly recommended expression, for example in the context of a calculated field in a query, is this:

Age: DateDiff("yyyy",[DOB],Date())+(Format([DOB],"mmdd")>Format(Date(),"mmdd"))

for the current age.  Or like this for the age at a specified date:

Age: DateDiff("yyyy",[DOB],[SpecifiedDate])+(Format([DOB],"mmdd")>Format([SpecifiedDate],"mmdd"))

This expression allows for the situation where the birthday in the current year has not yet happened.  It is a very useful formula, and will be accurate in almost all circumstances, including historical dates.

Birthday 29 February

In fact, as far as I know, the only time it won’t be accurate is in the case of a 29 February birthday, and the age is being evaluated on 28 February in a non leap year.  So, it’s pretty rare.

Nevertheless, the expression can be adjusted to cater to this special case:

DateDiff("yyyy",[DOB],Date())+((Format([DOB]+(Format([DOB],"mmdd")="0229" And Format(Date(),"mmdd")="0228" And Format(Date()+1,"mmdd")<>"0229"),"mmdd"))>Format(Date(),"mmdd"))

DateDiff("yyyy",[DOB],[SpecifiedDate])+((Format([DOB]+(Format([DOB],"mmdd")="0229" And Format([SpecifiedDate],"mmdd")="0228" And Format([SpecifiedDate]+1,"mmdd")<>"0229"),"mmdd"))>Format([SpecifiedDate],"mmdd"))

Not too difficult to use something like this, as is, whenever required within your database.  But a bit of a mouthful, I admit.

User Defined Function

Nevertheless, we can extend this same concept, and create a function that does the same thing.

In a Standard Module, copy the following code:

Public Function FindAge(DOB As Date, Optional DateFrom As Variant = 0) As Integer

Dim lEvalDOB As Long

Dim lEvalFrom As Long

Dim iAdjustLeap As Integer

Dim iAdjustMonth As Integer

Dim iAge As Integer

' define dates to use for evaluation of Age

' convert to Long Integer to allow for international date formats

If DateFrom = 0 Then

' assume current date

lEvalFrom = CLng(Date)

Else

lEvalFrom = CLng(DateFrom)

End If

lEvalDOB = CLng(DOB)

' if evaluation date is before date of birth, assume to return age of 0

If lEvalDOB > lEvalFrom Then

lEvalDOB = lEvalFrom

End If

' get the baseline difference in whole years

iAge = DateDiff("yyyy", lEvalDOB, lEvalFrom)

' adjust date to evaluate if date of birth is leap day

If Format(lEvalDOB, "mmdd") = "0229" Then

If Format(lEvalFrom, "mmdd") = "0228" And Format(lEvalFrom + 1, "mmdd") <> "0229" Then

End If

End If

lEvalDOB = lEvalDOB - iAdjustLeap

' adjust for current year birthday not reached

If Format(lEvalDOB, "mmdd") > Format(lEvalFrom, "mmdd") Then

End If

iAge = iAge - iAdjustMonth

' return function value

FindAge = iAge

End Function

Now, you can use this within the application.  For example, for the current age:

FindAge([DOB])

For the age at another specified date:

FindAge([DOB],[SpecifiedDate])

… with the appropriate syntax adjustments, depending on whether it is being used in a calculated field in a query, or in the Control Source of a calculated control on a form or report, or within a VBA procedure.

Disclaimer

This code makes the assumption that if the date where the age is being evaluated is before the date of birth, the Age will be 0, in other words we will not record a negative number as the age.  This is likely correct for most applications, but there may be specialised business scenarios where this assumption is not the correct one.

The code also assumes that for a 29 February date of birth, the person’s birthday will be regarded as 28 February in non leap years.  I understand that this model is not necessarily universally adhered to.

Conclusion

The above is an outline of one approach to derive Age in years accurately, based on Date of Birth.

Steve Schapel 