3
\$\begingroup\$

I am working on an app where I have to calculate the age of a person. Inside of my age class I have a function that is designed to account for leap year. Is there anything I am missing or could improve upon? I would have though this would have been more complicated so I am not confident in my method or my test case.

The function:

Function calculateAge() As Integer

    Dim age As Integer

    Try
        If Not Birthdate.Day.Equals(29) And Birthdate.Month.Equals(2) Then
            age = todaysDate.Year - Birthdate.Year
        Else
            age = todaysDate.Year - Birthdate.Year - 1
        End If

        Return age
    Catch ex As Exception
        Console.WriteLine(ex.ToString)
        Return Nothing
    Finally
        age = Nothing
    End Try

End Function

The test:

    Sub Main()

    'Test calculate age function'
    Console.WriteLine(chip.calculateAge)


    'Test calculate age function with a February 29th birthday'
    Dim steve As New clsAge("Steve")
    With steve
        .Birthdate = #2/29/2008#
    End With

    Dim date1 As DateTime = #2/29/2000#
    Dim date2 As DateTime = #2/28/2009#
    Dim age As Integer

    Console.WriteLine(date1.Day.ToString)


    If Not date1.Day.Equals(29) And date1.Month.Equals(2) Then
        age = date2.Year - date1.Year
        Console.WriteLine(age.ToString)
    Else
        age = date2.Year - date1.Year
        age = age - 1
        Console.WriteLine(age.ToString())
    End If

    Console.ReadLine()

End Sub
\$\endgroup\$
2
\$\begingroup\$

what about?

var date1 = DateTime.Parse("2/29/2000");
var date2 = DateTime.Parse("2/28/2009");

var years_old = date2.Subtract(date1).TotalDays / 365.25;
\$\endgroup\$
  • \$\begingroup\$ I like it. It's simple, but elegant. \$\endgroup\$ – Lance Collins Mar 22 '12 at 22:51
2
\$\begingroup\$

If you'd like to avoid magic strings when hardcoding 365.25 in your code, you can use the following code:

VB

Dim date1 As Date = DateTime.Parse("5/14/1994")
Dim date2 As Date = DateTime.Parse("5/13/2013")

Dim yearsOld as Integer = date2.Year - date1.Year
If date1.AddYears(yearsOld) > date2 Then yearsOld -=1

Console.WriteLine(yearsOld) '18

C#

var date1 = DateTime.Parse("5/14/1994");
var date2 = DateTime.Parse("5/13/2013");

int years_old = date2.Year - date1.Year;
if (date1 > date2.AddYears(-years_old)) years_old--;

Console.WriteLine(years_old); //18

I'm also suspicious (though I have not run enough test cases to confirm) that there are some pair of dates with the right number of leap years that will break the functionality implemented based on days of the year.

I wrote a blogpost about calculating age from dob as well, although it's in VB.NET

\$\endgroup\$
0
\$\begingroup\$

I doubt anyone will be using the code in the year 2100, but you should know that your solution would be off by a day if it was being used in that far flung future.

In the Gregorian calendar 3 criteria must be taken into account to identify leap years:

  • The year is evenly divisible by 4;
  • If the year can be evenly divided by 100, it is NOT a leap year, unless;
  • The year is also evenly divisible by 400. Then it is a leap year. This means that 2000 and 2400 are leap years, while 1800, 1900, 2100, 2200, 2300 and 2500 are NOT leap years.

Source

Basically, the year 2000 was a fluke. To really do it right, you have to take all of the criteria above into account. I imagine many programmers will be dealing with the Y21H bug about 80 years from now.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.