How would you calculate the age in C# using date of birth (considering leap years)

前端 未结 6 1863
傲寒
傲寒 2020-12-21 07:02

Here is a problem. I have seen many solutions, but no one seems to be fulfilling the criteria I want...

I want to display the age in this format

20 y         


        
6条回答
  •  生来不讨喜
    2020-12-21 07:36

    Age is pretty tricky. Here's the relevant excerpts from a struct I use.

    public struct Age
    {
        private readonly Int32 _years;
        private readonly Int32 _months;
        private readonly Int32 _days;
        private readonly Int32 _totalDays;
    
        /// 
        /// Initializes a new instance of .
        /// 
        /// The date and time when the age started.
        /// The date and time when the age ended.
        /// This 
        public Age(DateTime start, DateTime end)
            : this(start, end, CultureInfo.CurrentCulture.Calendar)
        {
        }
    
        /// 
        /// Initializes a new instance of .
        /// 
        /// The date and time when the age started.
        /// The date and time when the age ended.
        /// Calendar used to calculate age.
        public Age(DateTime start, DateTime end, Calendar calendar)
        {
            if (start > end) throw new ArgumentException("The starting date cannot be later than the end date.");
    
            var startDate = start.Date;
            var endDate = end.Date;
    
            _years = _months = _days = 0;
            _days += calendar.GetDayOfMonth(endDate) - calendar.GetDayOfMonth(startDate);
            if (_days < 0)
            {
                _days += calendar.GetDaysInMonth(calendar.GetYear(startDate), calendar.GetMonth(startDate));
                _months--;
            }
            _months += calendar.GetMonth(endDate) - calendar.GetMonth(startDate);
            if (_months < 0)
            {
                _months += calendar.GetMonthsInYear(calendar.GetYear(startDate));
                _years--;
            }
            _years += calendar.GetYear(endDate) - calendar.GetYear(startDate);
    
            var ts = endDate.Subtract(startDate);
            _totalDays = (Int32)ts.TotalDays;
        }
    
        /// 
        /// Gets the number of whole years something has aged.
        /// 
        public Int32 Years
        {
            get { return _years; }
        }
    
        /// 
        /// Gets the number of whole months something has aged past the value of .
        /// 
        public Int32 Months
        {
            get { return _months; }
        }
    
        /// 
        /// Gets the age as an expression of whole months.
        /// 
        public Int32 TotalMonths
        {
            get { return _years * 12 + _months; }
        }
    
        /// 
        /// Gets the number of whole weeks something has aged past the value of  and .
        /// 
        public Int32 Days
        {
            get { return _days; }
        }
    
        /// 
        /// Gets the total number of days that have elapsed since the start and end dates.
        /// 
        public Int32 TotalDays
        {
            get { return _totalDays; }
        }
    
        /// 
        /// Gets the number of whole weeks something has aged past the value of  and .
        /// 
        public Int32 Weeks
        {
            get { return (Int32) Math.Floor((Decimal) _days/7); }
        }
    
        /// 
        /// Gets the age as an expression of whole weeks.
        /// 
        public Int32 TotalWeeks
        {
            get { return (Int32) Math.Floor((Decimal) _totalDays/7); }
        }
    }
    

    Here's an example unit test that passes:

        [Test]
        public void Should_be_exactly_20_years_old()
        {
            var now = DateTime.Now;
            var age = new Age(now.AddYears(-20), now);
    
            Assert.That(age, Has.Property("Years").EqualTo(20)
                .And.Property("Months").EqualTo(0)
                .And.Property("Days").EqualTo(0));
        }
    

提交回复
热议问题