Code Samples for Businesses, Schools & Developers

First Published 18 Apr 2022                               Last Updated 28 June 2023


A question that comes up frequently in online forums is how to calculate a person's age in Access.
For example, see this thread at Access World Forums: Age Calculation or this one at Microsoft Tech Community: Calculating Age in Access

A wide variety of solutions are available; some better than others
This article covers several solutions which you can use depending on the degree of accuracy required.

First of all, lets consider two poor solutions:

One very simple approach just subtracts the birth year from the current year

Public Function Age(DOB As Date)

      Year(Date) - Year(DOB)

End Function


This works if the person has already had their birthday this year but gives an incorrect answer if not.
For example, if the current date is 17 April 2022:
a)   DOB: 31 Mar 2012:     Year(#2022-04-17#)-Year(2012-03-31#)=2022-2012 = 10       CORRECT
b)   DOB: 31 Sept 2012:     Year(#2022-04-17#)-Year(2012-09-31#)=2022-2012 = 10       INCORRECT - should be 9

Another very simple, but also unreliable, calculation uses the average number of days in a year, allowing for a leap year every 4 years i.e. 365.25.

Public Function Age(DOB As Date)

      Age = Int((Date - DOB) / 365.25)

End Function


Errors can most easily be seen by testing on a person's birthday
The following tests were done on #4/17/2022# for people with a birthday on that date

InaccurateAgeCalc
Alternate values above are incorrect

NOTE: A more accurate value for the average days in a year is 365.242199.
Using that figure would give much greater reliability but occasional errors will still occur

For calendar dates, an additional leap year correction is done every 100/400 years.
A centurial year is only a leap year if it is also divisible by 400. For example, 2000 was a leap year but 1900 & 2100 are not.
That adjustment brings the average length of the year to 365.2425 days, which is very close to the actual number.

All the remaining functions listed below do work reliably
In all cases, valid solutions include a check on whether the person has already had their birthday in the current year.

NOTE: All dates MUST be in mm/dd/yyyy or yyyy-mm-dd format



1.   Age in Years

Function AgeYr(DOB As Date) As Integer

      'age in years
      AgeYr = DateDiff("yyyy", DOB, Date) + (Format(DOB, "mmdd") > Format(Date, "mmdd"))

End Function


Typical usage: AgeYr(#1982-07-27#) = 39       or AgeYr(#07/27/1982#) = 39

The next function calculates age between 2 dates e.g. birth & death dates

Function AgeYears(datDate1 As Date, datDate2 As Date) As Integer

      'age in years between 2 dates
      If datDate1 <= datDate2 Then
            AgeYears = DateDiff("yyyy", datDate1, datDate2) + (Format(datDate1, "mmdd") > Format(datDate2, "mmdd"))
      Else
            AgeYears = Abs(DateDiff("yyyy", datDate1, datDate2) + (Format(datDate1, "mmdd") > Format(datDate2, "mmdd"))) - 1
      End If

End Function


Typical usage: AgeYears(#1952-07-27#, #2008-04-13#) = 55



2.   Age in Years and Months

Public Function AgeYearMonth(DOB As Date)

     'calculate age in years & months
      AgeYearMonth = DateDiff("yyyy", [DOB], Date) + (Format([DOB], "mmdd") > Format(Date, "mmdd")) & "yr " & _
                  (Month(Date) - Month([DOB]) + 12 + (Day(Date) < Day([DOB]))) Mod 12 & "m"


End Function


Typical usage: AgeYearMonth(#1965-08-14#) = 56yr 8m (on 17 Apr 2022)



3.   Age in Years, Months And Days

Most age functions only deal with years & months
The next function that also includes days & appears to work perfectly:

NOTE: Modified 8 May 2022 to make end date argument optional

Public Function CalcAge(dteDOB As Date, Optional dteEnd As Date) As String

      'years, months & days
      Dim intYears As Integer, intMonths As Integer, intDays As Integer

      'If no end date supplied, use current date as default
      If Nz(dteEnd, 0) = 0 Then dteEnd = Date

      intMonths = DateDiff("m", dteDOB, dteEnd)
      intDays = DateDiff("d", DateAdd("m", intMonths, dteDOB), dteEnd)

      If intDays < 0 Then
            intMonths = intMonths - 1
            intDays = DateDiff("d", DateAdd("m", intMonths, dteDOB), dteEnd)
      End If

      intYears = intMonths \ 12
      intMonths = intMonths Mod 12

      CalcAge = intYears & " Years, " & intMonths & " Months And " & intDays & " Days"

      'Debug.Print CalcAge

End Function


Typical usage: CalcAge(#1965-08-14#, #2022-04-17#) = 56 Years, 8 Months And 3 Days (on 17 Apr 2022)



UPDATE 4 May 2022

4.   Age in Years, Months, Days, Hours, Minutes And Seconds

I added this function in response to a request from David Nealey on LinkedIn.

NOTE:
David spent much of his working life as an astrogeologist so is used to thinking in terms of very precise time intervals - both large & small.
As astrogeologists always say: Space Rocks!

I decided to 'humour' David's request as adding the extra level of precision was easy enough to do . . . but of course the result is out of date 1 second later!

I decided to name the function NealeyAge 😁

NOTE: Modified 8 May 2022 to make end date argument optional

Public Function NealeyAge(dteDOB As Date, Optional dteEnd As Date) As String

      'years, months, days, hours, minutes and seconds!
      'named after David Nealey who wanted to know ages to the nearest second!

      Dim intYears As Integer, intMonths As Integer, intDays As Integer, bytHour As Byte, bytMin As Byte, bytSec As Byte
      Dim lngTimeDiff As Double

      'If no end date supplied, use Now as default
      If Nz(dteEnd, 0) = 0 Then dteEnd = Now

      'Get time difference part in seconds (86400 seconds in a day)
      lngTimeDiff = CLng(86400 * (GetRemainder(dteEnd) - GetRemainder(dteDOB)))

      intMonths = DateDiff("m", dteDOB, dteEnd)

      intDays = DateDiff("d", DateAdd("m", intMonths, dteDOB), dteEnd)

      If intDays < 0 Then
            intMonths = intMonths - 1
            intDays = DateDiff("d", DateAdd("m", intMonths, dteDOB), dteEnd)
      End If

      intYears = intMonths \ 12
      intMonths = intMonths Mod 12

      'adjust if time difference is negative
      If lngTimeDiff < 0 Then
            intDays = intDays - 1 'subtract a day
            lngTimeDiff = 86400 + lngTimeDiff 'recalculate number of seconds
      End If

      NealeyAge = intYears & " Years, " & intMonths & " Months, " & intDays & " Days, " & GetTimeDifference(lngTimeDiff)

End Function

======================================

Function GetRemainder(dteDate As Date)

      'returns the decimal part of an expression
      GetRemainder = CDbl(dteDate) - Int(CDbl(dteDate))

End Function

======================================

Function GetTimeDifference(lngTimeDiff)

      'creates a text string for the time part of the calculation
      Select Case lngTimeDiff

      Case Is < 60
            GetTimeDifference = "0 Hours, 0 Minutes And " & lngTimeDiff & " Seconds"

      Case Is < 3600
            GetTimeDifference = "0 Hours, " & (lngTimeDiff \ 60) & " Minutes And " & (lngTimeDiff Mod 60) & " Seconds"

      Case Is < 86400
            GetTimeDifference = (lngTimeDiff \ 3600) & " Hours, " & ((lngTimeDiff Mod 3600) \ 60) & " Minutes And " & (lngTimeDiff Mod 60) & " Seconds"

      End Select

End Function



Typical usage:
NealeyAge(#5/15/1952 7:23:51 PM#, #5/4/2022 11:59:47 PM#) = 69 Years, 11 Months, 19 Days, 4 Hours, 35 Minutes And 56 Seconds



Updates:

1.   4 May 2022 - added NealeyAge function
2.   8 May 2022 - end date argument in CalcAge & NealeyAge functions now optional with default as current date / now respectively


I hope that one or more of the valid functions given above will be useful to other developers
Please let me know if you discover any specific example where a function gives an incorrect answer



Additional Info - 26 June 2023:

1.   Leap Year Birthdays

Some time ago I had a fairly lengthy exchange with another MVP at Bytes.com where we disagreed about when someone born on Feb 29 in a leap year would officially become one year older in non-leap years and how Access should treat such calculations.

To summarise that exchange, his view was that Feb 28 should then be used as their birthdate was the last day of Feb whereas I stated that should occur on 1 March as someone is only considered to be one year older once the calendar reaches their birth date. Both viewpoints have some validity.

The reality is for legal purposes, each country makes a choice about which to use. So neither of us was necessarily completely correct in terms of the law.


2.   Korean Age

I read an interesting article today about ‘Korean age’: South Koreans become younger under new age-counting law - BBC News

I’m very thankful that I never had to calculate age the traditional South Korean way where people were considered to be age 1 at birth and became one year older on 1 Jan each year. So, on that system, someone born on 31 Dec 2022 was aged 2 on 1 Jan 2023!

Thankfully, the old South Korean system has just been scrapped.


3.   More Date/Time Functions

Fellow MVP, Gustav Brock, has a GitHub repository with a wide range of Date/Time functions. See VBA.Date



Feedback

Please use the contact form below to let me know whether you found this article interesting/useful or if you have any questions/comments.

Please also consider making a donation towards the costs of maintaining this website. Thank you



Colin Riddington           Mendip Data Systems                 Last Updated 28 June 2023



Return to Code Samples Page




Return to Top