13

anyone know how to get the age based on a date(birthdate)

im thinking of something like this

string age = DateTime.Now.GetAccurateAge();

and the output will be some thing like 20Years 5Months 20Days

FrustratedWithFormsDesigner
  • 26,726
  • 31
  • 139
  • 202
reggieboyYEAH
  • 870
  • 3
  • 11
  • 28

14 Answers14

61
public static class DateTimeExtensions
{
    public static string ToAgeString(this DateTime dob)
    {
        DateTime today = DateTime.Today;

        int months = today.Month - dob.Month;
        int years = today.Year - dob.Year;

        if (today.Day < dob.Day)
        {
            months--;
        }

        if (months < 0)
        {
            years--;
            months += 12;
        }

        int days = (today - dob.AddMonths((years * 12) + months)).Days;

        return string.Format("{0} year{1}, {2} month{3} and {4} day{5}",
                             years, (years == 1) ? "" : "s",
                             months, (months == 1) ? "" : "s",
                             days, (days == 1) ? "" : "s");
    }
}
LukeH
  • 263,068
  • 57
  • 365
  • 409
  • 1
    This is the only good answer. It's a shame it's not voted higher. – Gabe Jan 02 '12 at 06:55
  • 29-1-1967 to 1-3-1999 gives 32years 1 month and zero days. The correct is 32y 1m and 1 day, since adding 32y+1m to 29-1-1967 you will get 28-2-1999 – Panos Theof Apr 10 '16 at 15:15
  • 1
    @Panos: Thanks, well spotted. That's a nasty bug that's been in there for a long time. I've fixed it now. – LukeH Apr 11 '16 at 11:30
  • Still has a bug: 30-1-1967 to 29-3-1999 gives 32y 1m and 28days instead of 29days. I posted an answer with the bug fixed – Panos Theof Apr 11 '16 at 14:40
  • 29-2-1968 to 1-1-1999 := 30y 10m 4days instead of 3days. That is if adding 30years and 10months to 29-2-1968 you get 29-12-1998 or 28-12-1998. I think 29 is the correct one – Panos Theof Apr 14 '16 at 07:38
  • 1
    @Panos: Fixed yet again. Sorry about this :( – LukeH Apr 14 '16 at 11:02
  • 2
    @LukeH: Thank you. The latest version passes all my tests! – Panos Theof Apr 16 '16 at 12:14
  • @LukeH it is calculated wrong days and months for 01-02-2014 to 19-05-2014. It also give me 01-07-2015 to 30-06-2016 11 months 30 days instead of giving me 12 months. your opinion – ZahidKakar Nov 14 '19 at 11:57
  • It gets weird for leap babies. This method calculates that 2/28/2017 (a common year) is 1 year 0 days after 2/28/2016, 11 mo 30 days after 2/29/2016, and 11 mo 27 days after 3/1/2016. The 28ths are 266 days apart. Considering this is the baby's first year alive and the 29th was a catchup day to account for the previous 4 years, I would argue the baby is 1 year 1 day old on that day (I might also argue babies born on the 29th should be recorded as born on 2/28 for that reason...) But more strange is the 3 day jump between 2/29 and 3/1. Doesn't seem right – xr280xr Feb 05 '20 at 19:40
  • Very good answer it working fine without any issue. – Santosh Kumar Feb 08 '21 at 06:21
  • This code is not giving accurate figure in days in the following case: DoB: Mar 22 1972 to Oct 16 2022 --- It gives: 60y 6m 24d Whereas two online sites are giving 60y 6m 25d Below are those sites i tested at: [link](https://www.calculator.net/age-calculator.html) and [link](https://www.easycalculation.com/date-day/age-calculator.php) – Syed Irfan Ahmad Oct 16 '22 at 18:44
5

See the answers at How do I calculate someone’s age in C#? for ideas.

Community
  • 1
  • 1
Jonathan S.
  • 5,837
  • 8
  • 44
  • 63
3

Not certain that it would always be correct (haven't thought about if there's some cases with leap years etc that might make it fail...), but this is an easy way to get out the year and month:

DateTime bd = DateTime.Parse("2009-06-17");
TimeSpan ts = DateTime.Now.Subtract(bd);
DateTime age = DateTime.MinValue + ts;
string s = string.Format("{0} Years {1} months {2} days", age.Year -1 , age.Month - 1, age.Day - 1);
Hans Olsson
  • 54,199
  • 15
  • 94
  • 116
  • That can definitely be incorrect. DateTime.MinValue + ts` probably has a different number of days (leap years, etc.) than the actual date range we're dealing with. – Nelson Rothermel Jun 16 '10 at 15:41
  • @Nelson: Not sure though, if you use `1970-06-16` as the bd it returns 40 years exactly, which is correct, and that date range spans quite a few leap years. – Hans Olsson Jun 16 '10 at 15:47
  • But do `1900-06-16` and now you have +1 day. It's very close, but not exact. – Nelson Rothermel Jun 16 '10 at 16:11
  • In this specific case, it seems to be incorrect once you get over 100 years. I'm not sure if there are other problems or not. This may be close enough and not worth any extra effort. – Nelson Rothermel Jun 16 '10 at 16:12
3

Since i can't post code to a comment, here it is the code based on @LukeH answer, with the bug fixed

public static int GetAge( DateTime dob, DateTime today, out int days, out int months ) {
        DateTime dt = today;
        if( dt.Day < dob.Day ) {
            dt = dt.AddMonths( -1 );
        }

        months = dt.Month - dob.Month;
        if( months < 0 ) {
            dt = dt.AddYears( -1 );
            months += 12;
        }

        int years = dt.Year - dob.Year;
        var offs = dob.AddMonths( years * 12 + months );
        days = (int)( ( today.Ticks - offs.Ticks ) / TimeSpan.TicksPerDay );
        return years;
    }
Panos Theof
  • 1,450
  • 1
  • 21
  • 27
  • it is giving -6days if calculated from Mar 22 1972 to Oct 16 2022 – Syed Irfan Ahmad Oct 16 '22 at 18:56
  • That is not true! int years = GetAge(new DateTime(1972, 3, 22), new DateTime(2022, 10, 16), out int days, out int months); Debug.WriteLine($"years:{years},months:{months},days:{days}"); > years:50,months:6,days:24 – Panos Theof Oct 17 '22 at 15:29
3

My answer is not exactly an answer; it is a way to find an answer in this and similar threads. The correct answer has already been provided by LukeH, and my 2 cents here is for anyone that want to know which is the more correct answer*.

*more correct because, as you saw in several discussions and comments scattered around, we have to compromise with some preconditions in leap years - dob is 1-mar or 28-feb in normal years?

I'm using as benchmark this and this other sites that do that, and my brain too ;)

I implemented LukeH, @Panos Theof and @xr280xr answers here:

public static class DateTimeExtensions
{
    public static int HowOld(this DateTime initialDay, DateTime dayToCalculate, out int days, out int months)
    {
        //https://stackoverflow.com/a/3055445/2752308
        //LukeH: essentially right
        months = dayToCalculate.Month - initialDay.Month;
        int years = dayToCalculate.Year - initialDay.Year;

        if (dayToCalculate.Day < initialDay.Day)
        {
            months--;
        }

        if (months < 0)
        {
            years--;
            months += 12;
        }

        days = (dayToCalculate - initialDay.AddMonths((years * 12) + months)).Days;
        Console.WriteLine(
            $"{years} year{((years == 1) ? "" : "s")}, {months} month{((months == 1) ? "" : "s")} and {days} day{((days == 1) ? "" : "s")}");
        return years;
    }
    public static int HowOld2(this DateTime dob, DateTime today, out int days, out int months ) {
        //@Panos Theof: right
        DateTime dt = today;
        if( dt.Day < dob.Day ) {
            dt = dt.AddMonths( -1 );
        }

        months = dt.Month - dob.Month;
        if( months < 0 ) {
            dt = dt.AddYears( -1 );
            months += 12;
        }

        int years = dt.Year - dob.Year;
        var offs = dob.AddMonths( years * 12 + months );
        days = (int)( ( today.Ticks - offs.Ticks ) / TimeSpan.TicksPerDay );
        return years;
    }
    public static int HowOld2a(this DateTime initialDay, DateTime dayToCalculate, out int days, out int months)
    {
        //@From were I do not know ;) wrong

        months = dayToCalculate.Month - initialDay.Month;
        int years = dayToCalculate.Year - initialDay.Year;

        if (dayToCalculate.Day < initialDay.Day)
        {
            dayToCalculate = dayToCalculate.AddMonths(-1);
        }

        if (months < 0)
        {
            dayToCalculate = dayToCalculate.AddYears(-1);
            months += 12;
        }
        years = dayToCalculate.Year - initialDay.Year;
        var offs = initialDay.AddMonths(years * 12 + months);
        days = (int)((dayToCalculate.Ticks - offs.Ticks) / TimeSpan.TicksPerDay);
        Console.WriteLine(
            $"{years} year{((years == 1) ? "" : "s")}, {months} month{((months == 1) ? "" : "s")} and {days} day{((days == 1) ? "" : "s")}");
        return years;
    }
    public static int HowOld3(this DateTime initialDay, DateTime dayToCalculate, out int days, out int months)
    {
        //@xr280xr: wrong

        //Get the relative difference between each date part
        days = dayToCalculate.Day - initialDay.Day;
        months = dayToCalculate.Month - initialDay.Month;
        int years = dayToCalculate.Year - initialDay.Year;

        if (days < 0)
        {
            days = DateTime.DaysInMonth(initialDay.Year, initialDay.Month) - initialDay.Day +    //Days left in month of birthday +
                   dayToCalculate.Day;                                                                   //Days passed in dayToCalculate's month
            months--;                                                                               //Subtract incomplete month that was already counted
        }

        if (months < 0)
        {
            months += 12;   //Subtract months from 12 to convert relative difference to # of months
            years--;        //Subtract incomplete year that was already counted
        }

        Console.WriteLine(string.Format("{0} ano{1}, {2} mes{3} e {4} day{5}",
            years, (years == 1) ? "" : "s",
            months, (months == 1) ? "" : "es",
            days, (days == 1) ? "" : "s"));
        //$"{years} ano{((years == 1) ? "" : "s")}, {months} {((months == 1) ? "mês" : "meses")} e {days} dia{((days == 1) ? "" : "s")}");
        return years;
    }
}

Using VS2019 and XUnit I create an Inlinedata generator Class:

   public class CalculatorTestData : IEnumerable<object[]>
            public IEnumerator<object[]> GetEnumerator()
            {
                yield return new object[] { new DateTime(1966, 7, 27), new DateTime(2020, 7, 26), 53, 11, 29 };
                yield return new object[] { new DateTime(1966, 7, 27), new DateTime(2020, 7, 27), 54, 0, 0 };
                yield return new object[] { new DateTime(1966, 7, 27), new DateTime(2020, 7, 28), 54, 0, 1 };
                yield return new object[] { new DateTime(1968, 2, 29), new DateTime(2020, 2, 28), 51, 11, 30 };
                yield return new object[] { new DateTime(1968, 2, 29), new DateTime(2020, 2, 29), 52, 0, 0 };
                yield return new object[] { new DateTime(1968, 2, 29), new DateTime(2020, 3, 01), 52, 0, 1 };
                yield return new object[] { new DateTime(2016, 2, 29), new DateTime(2017, 2, 28), 0, 11, 30 };
            }

            IEnumerator<object[]> IEnumerable<object[]>.GetEnumerator() => GetEnumerator();
            IEnumerator IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }
        }

And setup for the three methods:

    public class CalculatorTestData : IEnumerable<object[]>
    { 
        public IEnumerator<object[]> GetEnumerator()
        {
            //https://www.timeanddate.com/date/durationresult.html?d1=27&m1=07&y1=1966&d2=26&m2=07&y2=2020
            // (both 28/02 and 29/02 produce 52, 0, 0)
            // (01/03 yields 52, 0, 2 !!!???)
            // (Feb 29, 2016 and Feb 28, 2017 => 1 y, 0 m, 1 d!!!???)

            //https://www.calculator.net/date-calculator.html
            //^^^^ (only 28/02 produces 52, 0, 0; others right)
            // (Feb 29, 2016 and Feb 28, 2017 => 11 m, 30 d)
            yield return new object[] { new DateTime(1966, 7, 27), new DateTime(2020, 7, 26), 53, 11, 29 };
            yield return new object[] { new DateTime(1966, 7, 27), new DateTime(2020, 7, 27), 54, 0, 0 };
            yield return new object[] { new DateTime(1966, 7, 27), new DateTime(2020, 7, 28), 54, 0, 1 };
            yield return new object[] { new DateTime(1968, 2, 29), new DateTime(2020, 2, 28), 51, 11, 30 };
            yield return new object[] { new DateTime(1968, 2, 29), new DateTime(2020, 2, 29), 52, 0, 0 };
            yield return new object[] { new DateTime(1968, 2, 29), new DateTime(2020, 3, 01), 52, 0, 1 };
            yield return new object[] { new DateTime(2016, 2, 29), new DateTime(2017, 2, 28), 0, 11, 30 };
        }

        IEnumerator<object[]> IEnumerable<object[]>.GetEnumerator() => GetEnumerator();
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
    [Theory]
    [ClassData(typeof(CalculatorTestData))]
    public void TestHowOld(DateTime initialDay, DateTime dayToCalculate,int expectedYears, int expectedMonths, int expectedDays)//, out int days, out int months
    {
        //LukeH: essentially right
        int resultMonths, resultDays;
        int age = initialDay.HowOld(dayToCalculate,out resultDays,
            out resultMonths); 
        Assert.Equal(age, expectedYears);
        Assert.Equal(resultMonths, expectedMonths);
        Assert.Equal(resultDays, expectedDays);
        //https://stackoverflow.com/a/3055445/2752308 //LukeH
    }
    [Theory]
    [ClassData(typeof(CalculatorTestData))]
    public void TestHowOld2(DateTime initialDay, DateTime dayToCalculate, int expectedYears, int expectedMonths, int expectedDays)//, out int days, out int months
    {
        //@Panos Theof: right
        int resultMonths, resultDays;
        int age = initialDay.HowOld2(dayToCalculate, out resultDays,
            out resultMonths); 
        Assert.Equal(age, expectedYears);
        Assert.Equal(resultMonths, expectedMonths);
        Assert.Equal(resultDays, expectedDays);

    }
    [Theory]
    [ClassData(typeof(CalculatorTestData))]
    public void TestHowOld2a(DateTime initialDay, DateTime dayToCalculate, int expectedYears, int expectedMonths, int expectedDays)//, out int days, out int months
    {
        //@Unknow guy: wrong
        int resultMonths, resultDays;
        int age = initialDay.HowOld2a(dayToCalculate, out resultDays,
            out resultMonths); 
        Assert.Equal(age, expectedYears);
        Assert.Equal(resultMonths, expectedMonths);
        Assert.Equal(resultDays, expectedDays);

    }
    [Theory]
    [ClassData(typeof(CalculatorTestData))]
    public void TestHowOld3(DateTime initialDay, DateTime dayToCalculate, int expectedYears, int expectedMonths, int expectedDays)//, out int days, out int months
    {
        //@xr280xr: wrong
        int resultMonths, resultDays;
        int age = initialDay.HowOld3(dayToCalculate, out resultDays,
            out resultMonths); 
        Assert.Equal(age, expectedYears);
        Assert.Equal(resultMonths, expectedMonths);
        Assert.Equal(resultDays, expectedDays);

    }

The expected results are on the InlineData Class, of course.

The output results are:

Output of Unit-tests

So, LukeH and @Panos Theof has the correct answer. And, for my surprise, both sites disagree for leap DOB, and IMHO Calculator.net is correct, and timeanddate.com plainly wrong, producing this error outputs:

For DOB Feb 29:

  • both 28/02 and 29/02 produce 52, 0, 0 (?!)

  • 01/03 yields 52, 0, 2 (!!!???)

  • Feb 29, 2016 => Feb 28, 2017 => 1 y, 0 m, 1 d (!!!???)

Hope showing the test setup helps someone.

  • 1
    The implementation that you claim is mine, has nothing to do with my code. You compute months diff for example before computing dayToCalculate. That's not the order my code does the computations – Panos Theof Oct 17 '22 at 16:32
  • 1
    @PanosTheof, I will revisit my comparison code and see if I had made a mistake with the links that I followed. If so, I'll correct it, of course. – Marcelo Scofano Diniz Oct 17 '22 at 18:33
  • 1
    @PanosTheof, you are absolutely right. The other code is from other source. Yours are correct too. I updated all code and prints above. Thanks for point it. – Marcelo Scofano Diniz Oct 18 '22 at 03:28
2

See http://techbrij.com/210/convert-timespan-to-year-month-date-age-calculation-in-net

Gabe
  • 84,912
  • 12
  • 139
  • 238
this. __curious_geek
  • 42,787
  • 22
  • 113
  • 137
2

This is what I use. It's a combination of the selected answer and this answer.

For someone born on 2016-2-29, on the 2017-3-1 their age outputs:

Years: 1
Months: 1 (28 days for February)
Days: 0

var today = new DateTime(2020,11,4);
//var today = DateTime.Today;

// Calculate the age.
var years = today.Year - dateOfBirth.Year;

// Go back to the year in which the person was born in case of a leap year
if (dateOfBirth.Date > today.AddYears(-years))
{
    years--;
}

var months = today.Month - dateOfBirth.Month;
// Full month hasn't completed
if (today.Day < dateOfBirth.Day)
{
    months--;
}

if (months < 0)
{
    months += 12;
}

Years = years;
Months = months;
Days = (today - dateOfBirth.AddMonths((years * 12) + months)).Days;
whiscode
  • 2,301
  • 1
  • 12
  • 7
0

Here is what I use:

    public static int GetAge(DateTime dateOfBirth)
    {
        int age = DateTime.Now.Year - dateOfBirth.Year;
        if (dateOfBirth.AddYears(age) > DateTime.Now)
        {
            age = age - 1;
        }

        return age;
    }
Ian
  • 170
  • 1
  • 6
0

To get the age I would use the datetime of the birthdate and find the difference between that and the current system time. This link shows how to find the difference between two datetimes. Just make the starttime be the user's birthdate and endtime be now (DateTime.Now;)

Kyra
  • 5,129
  • 5
  • 35
  • 55
0

This sounds like a fine exercise to get to know the TimeSpan class better.

Thomas Kjørnes
  • 1,928
  • 1
  • 17
  • 17
  • TimeSpan doesn't represent time with fields for Years or Months. Largest unit there is Days and converting days to Months or Years is messy. – FirstVertex Sep 24 '15 at 16:24
0
@if (Model.CF_DateOfBirth.HasValue)
                                        {
                                            var today = DateTime.Today;
                                            var months = DateTime.Today;
                                            var age = today.Year - Model.CF_DateOfBirth.Value.Year;
                                            var mons = months.Month - Model.CF_DateOfBirth.Val`enter code here`ue.Month;
                                            if (Model.CF_DateOfBirth > today.AddYears(-age) && Model.CF_DateOfBirth>months.AddMonths(-mons))
                                            {
                                                age--; mons--;
                                            }
                                            <i class="" style="color:cadetblue">&nbsp;&nbsp;Date of birth:&nbsp;&nbsp;</i><b style="color:teal">@Convert.ToDateTime(Model.CF_DateOfBirth).ToShortDateString().ToString()</b> <span>&nbsp;&nbsp;(&nbsp;<b>@age</b>Years &nbsp;<b>@mons</b> Months)</span>

                                        }
0

I find this the most accurate.

            private int GetAge(DateTime birthDate)
            {
                TimeSpan ageTimeSpan = DateTime.UtcNow.Subtract(birthDate);
                int age = new DateTime(ageTimeSpan.Ticks).Year;
                return age;
            }
Noob
  • 710
  • 11
  • 15
  • I have a lingering suspicion you might run into funny issues with the way the calendar has been structured during the first century AC. I would advice caution with this method. – XDS Aug 11 '19 at 10:09
0

I was noticing peculiarities with LukeH's answer and leap years. The simplest example is probably a dob = 2/29/2016 as of 2/28/2017 and 3/1/2017. The way I look at it, there are no days left in Feb 2016, there are 11 complete months (Mar-Jan) in between, and there have been 28 days in Feb 2017 so far, so as of 2/28/2017, I would call this person 11 months 28 days old. And 1 year 1 day old as of 3/1/2017. (Although some leap day babies do celebrate and on the 28th of common years ... I'm curious what the legal consideration is.)

Because LukeH's method makes uses of DateTime.AddMonths, it calculates 11 months 30 days, because it finds the difference in days between 2/28/2017 and 1/29/2017. So it calculates that 2/28/2017 is 11 mo 30 days after 2/29/2016, and 11 mo 27 days after 3/1/2016. A 3 day age difference for birthdays only 1 day apart. If it came up with 28 days as I did "by hand" they would have a one day age difference.

I'm not exactly sure how to describe the fundamental difference in approaches, but here is my stab at it. It seems there is always a gotcha with dates so please scrutinize.

internal static void CalculateAge(DateTime dateOfBirth, DateTime asOfDate, out int years, out int months, out int days)
{
    Console.Write("As of " + asOfDate.ToShortDateString() + ": ");

    //Get the relative difference between each date part
    days = asOfDate.Day - dateOfBirth.Day;
    months = asOfDate.Month - dateOfBirth.Month;
    years = asOfDate.Year - dateOfBirth.Year;

    if (days < 0)
    {
        days = DateTime.DaysInMonth(dateOfBirth.Year, dateOfBirth.Month) - dateOfBirth.Day +    //Days left in month of birthday +
                asOfDate.Day;                                                                   //Days passed in asOfDate's month
        months--;                                                                               //Subtract incomplete month that was already counted
    }

    if (months < 0)
    {
        months += 12;   //Subtract months from 12 to convert relative difference to # of months
        years--;        //Subtract incomplete year that was already counted
    }

    Console.WriteLine(string.Format("{0} year{1}, {2} month{3} and {4} day{5}",
                years, (years == 1) ? "" : "s",
                months, (months == 1) ? "" : "s",
                days, (days == 1) ? "" : "s"));
}
xr280xr
  • 12,621
  • 7
  • 81
  • 125
0

If you have a Instance Variable/Property that names DateOfBirth, you can use this method. Otherwise, you can pass the Date of Birth as a parameter for method. I made some calculus and I proved that never fails.

public int AgeCalc(){
      DateTime now = DateTime.Now;
      double age =  Math.Floor((DateTime.Now - DateOfBirth).TotalDays)/((DateTime.IsLeapYear(year: now.Year)? 366 : 365));
      return (age % 1) >= 0.951 ? Math.Round(age) : Math.Floor(age);
}

I hope that this can help you :)

H4XOR
  • 1
  • 1
  • 1