C# calculate accurate age

前端 未结 14 1752
攒了一身酷
攒了一身酷 2020-12-15 11:01

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

im thinking of something like this

string age = DateTime.Now.GetAccurateAge();
相关标签:
14条回答
  • 2020-12-15 11:34

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

    0 讨论(0)
  • 2020-12-15 11:36

    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 :)

    0 讨论(0)
  • 2020-12-15 11:39

    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;
        }
    
    0 讨论(0)
  • 2020-12-15 11:41

    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 initialDay, DateTime dayToCalculate, out int days, out int months)
        {
            //@Panos Theof: 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} year{1}, {2} month{3} and {4} day{5}",
                years, (years == 1) ? "" : "s",
                months, (months == 1) ? "" : "s",
                days, (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:

        [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); //https://stackoverflow.com/questions/28970265/how-to-test-method-with-out-parameters
            Assert.Equal(age, expectedYears);
            Assert.Equal(resultMonths, expectedMonths);
            Assert.Equal(resultDays, expectedDays);
        }
        [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: wrong
            int resultMonths, resultDays;
            int age = initialDay.HowOld2(dayToCalculate, out resultDays,
                out resultMonths); //https://stackoverflow.com/questions/28970265/how-to-test-method-with-out-parameters
            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); //https://stackoverflow.com/questions/28970265/how-to-test-method-with-out-parameters
            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:

    So, LukeH 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.

    0 讨论(0)
  • 2020-12-15 11:42

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

    0 讨论(0)
  • 2020-12-15 11:44
    @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 讨论(0)
提交回复
热议问题