[AccessD] Age calculation function

Mark Whittinghill mwhittinghill at symphonyinfo.com
Mon Aug 11 10:05:19 CDT 2003


For, the record, this is what I ended up with.  It's pretty much Gustav's function, but I just tweaked it a bit on naming and minor things like that.  I also made it return a variant, since there are situations where I would want it to return null.  

The goal of this function is to return an age in integer years, as in my birthday is July 10, so I'm 35 on July 9, and 36 on July 10.  I have been unable to make this function return an incorrect value, assuming I don't give it impossible data.  If a person is born Feb 29, it uses Feb 28 for the birthday in non leap years.  Works for me.


Public Function CalculateAge(varBirth As Variant, varEndDate As Variant) As Variant
'This function will calculate age from birthday
' Just using datediff rounds up a year
'Variants are used, since this is also called from queries

' Thanks to Gustav Brock, Cactus Data ApS.

On Error GoTo eh

    Dim datBirth As Date
    Dim datEnd As Date
    
    If IsDate(varBirth) = False Then
        CalculateAge = Null
        GoTo ex
    End If
    
    If IsDate(varEndDate) = False Then
        CalculateAge = Null
        GoTo ex
    End If
    
    datBirth = CDate(varBirth)
    datEnd = CDate(varEndDate)
    
    CalculateAge = CalculateYears(datBirth, datEnd)
ex:
    Exit Function
eh:
    CalculateAge = -999
    Resume ex
End Function

Public Function CalculateYears(ByVal datDate1 As Date, ByVal datDate2 As Date) As Integer

' Returns the difference in full years between datDate1 and datDate2.
'
' Calculates correctly for:
'   negative differences
'   leap years
'   dates of 29. February
'   date/time values with embedded time values
'   negative date/time values (prior to 1899-12-29)
'
' Thanks toGustav Brock, Cactus Data ApS.

On Error GoTo eh

    ' Constants for leap year calculation. Last normal date of February.
    Const cbytFebMonth      As Byte = 2
    Const cbytFebLastDay    As Byte = 28
    ' Maximum number of days in a month.
    Const cbytMonthDaysMax  As Byte = 31
    
    Dim intYears            As Integer
    Dim intDaysDiff         As Integer
    Dim intReversed         As Integer
    
    
    intYears = DateDiff("yyyy", datDate1, datDate2)
    If intYears = 0 Then
      ' Both dates fall within the same year.
    Else
    
        ' Check for ultimo February and leap years.
        If (Month(datDate1) = cbytFebMonth) And (Month(datDate2) = cbytFebMonth) Then
            ' Both dates fall in February.
            ' Check if dates are at ultimo February.
            
            If (Day(datDate1) >= cbytFebLastDay) And (Day(datDate2) >= cbytFebLastDay) Then
                ' Both dates are at ultimo February.
                ' Check if the dates fall in leap years.
                
                If Day(DateSerial(Year(datDate1), cbytFebMonth + 1, 0)) = cbytFebLastDay Xor _
                    Day(DateSerial(Year(datDate2), cbytFebMonth + 1, 0)) = cbytFebLastDay Then
                    ' Only one date falls within a leap year.
                    ' Adjust both dates to day 28 of February.
                    datDate1 = DateAdd("d", cbytFebLastDay - Day(datDate1), datDate1)
                    datDate2 = DateAdd("d", cbytFebLastDay - Day(datDate2), datDate2)
                Else
                    ' Both dates fall either in leap years or non leap years.
                    ' No adjustment needed.
                End If
                
            End If
            
        End If
        
        ' Calculate day difference using months and days as Days() will fail when
        ' comparing leap years with non leap years for dates after February.
        intDaysDiff = (Month(datDate1) * cbytMonthDaysMax + Day(datDate1)) - (Month(datDate2) * cbytMonthDaysMax + Day(datDate2))
        intReversed = Sgn(intYears)
        ' Decrease count of years by one if dates are closer than one year.
        intYears = intYears + (intReversed * ((intReversed * intDaysDiff) > 0))
        
    End If
    
    CalculateYears = intYears
ex:
    Exit Function
eh:
    CalculateYears = -999
    Resume ex
End Function


Mark Whittinghill
Symphony Information Services
612-333-1311
mwhittinghill at symphonyinfo.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://databaseadvisors.com/pipermail/accessd/attachments/20030811/b83d1517/attachment-0001.html>


More information about the AccessD mailing list