【问题标题】:How do I calculate someone's age based on a DateTime type birthday?如何根据 DateTime 类型的生日计算某人的年龄?
【发布时间】:2010-09-05 05:27:34
【问题描述】:

给定一个代表一个人生日的DateTime,我如何计算他们的年龄?

【问题讨论】:

  • 到目前为止所有答案都遗漏的是,这取决于这个人出生在哪里以及他们现在在哪里。
  • @Yaur:只需将现在 + 出生的时间转换为 GMT/UTC,年龄只是一个相对值,因此时区无关紧要。要确定用户当前的时区,您可以使用 GeoLocating。
  • 如果我们考虑@Yaur 的跨时区计算建议,夏令时是否会以任何方式影响计算?
  • 请注意,对于不到一岁的人,他们的年龄以天、周或月为单位。单位的过渡时间可能因领域而异。
  • 我们都可以看到,年龄没有明确的定义。我遇到的许多女性倾向于将她们的生活时间四舍五入到一整年,直到二十多岁,然后她们开始四舍五入。我是 1 月 3 日出生的,所以无论是哪一天,我都会从我的出生年份中减去当前年份。有些人认为如果你出生在闰日,你的年龄是1/4。如果你出生在闰秒怎么办? 8个月的宝宝算1吗?如果我飞往西方,我会变年轻吗?如果我的心跳停止了一分钟,我应该把它包括在计算中吗?

标签: c# .net datetime


【解决方案1】:

无分支解决方案:

public int GetAge(DateOnly birthDate, DateOnly today)
{
    return today.Year - birthDate.Year + (((today.Month << 5) + today.Day - ((birthDate.Month << 5) + birthDate.Day)) >> 31);
}

【讨论】:

    【解决方案2】:

    这是一个非常简单的方法:

    int Age = DateTime.Today.Year - new DateTime(2000, 1, 1).Year;
    

    【讨论】:

      【解决方案3】:

      我强烈建议使用名为AgeCalculator 的 NuGet 包,因为在计算年龄(闰年、时间分量等)时需要考虑很多事情,并且只有两行代码不能解决问题。图书馆给你的时间不止一年。它甚至在计算时考虑了时间成分,因此您可以获得包含年、月、日和时间成分的准确年龄。将闰年的 2 月 29 日视为非闰年的 2 月 28 日更为先进。

      【讨论】:

        【解决方案4】:

        可以这样计算“年龄”(即“西方”方式):

        public static int AgeInYears(this System.DateTime source, System.DateTime target)
          => target.Year - source.Year is int age && age > 0 && source.AddYears(age) > target ? age - 1 : age < 0 && source.AddYears(age) < target ? age + 1 : age;
        

        如果时间方向为“负”,则年龄也为负。

        可以加一个分数,表示从目标到下一个生日累积的年龄:

        public static double AgeInTotalYears(this System.DateTime source, System.DateTime target)
        {
          var sign = (source <= target ? 1 : -1);
        
          var ageInYears = AgeInYears(source, target); // The method above.
        
          var last = source.AddYears(ageInYears);
          var next = source.AddYears(ageInYears + sign);
        
          var fractionalAge = (double)(target - last).Ticks / (double)(next - last).Ticks * sign;
        
          return ageInYears + fractionalAge;
        }
        

        分数是过去的时间(从上一个生日开始)与总时间(到下一个生日)的比率。

        无论是向前还是向后,这两种方法的工作方式都是一样的。

        【讨论】:

          【解决方案5】:
          var startDate = new DateTime(2015, 04, 05);//your start date
          var endDate = DateTime.Now;
          var years = 0;
          while(startDate < endDate) 
          {
               startDate = startDate.AddYears(1);
               if(startDate < endDate) 
               {
                   years++;
               }
          }
          

          【讨论】:

            【解决方案6】:

            这很简单,看起来很准确,可以满足我的需求。我出于闰年的目的做一个假设,无论这个人何时选择庆祝生日,他们在技术上不会老一岁,直到自上一个生日过去 365 天(即 2 月 28 日不会让他们老一岁) .

            DateTime now = DateTime.Today;
            DateTime birthday = new DateTime(1991, 02, 03);//3rd feb
            
            int age = now.Year - birthday.Year;
            
            if (now.Month < birthday.Month || (now.Month == birthday.Month && now.Day < birthday.Day))//not had bday this year yet
              age--;
            
            return age;
            

            【讨论】:

              【解决方案7】:

              我对@9​​87654321@一无所知,但我能做的就是:

              using System;
                                  
              public class Program
              {
                  public static int getAge(int month, int day, int year) {
                      DateTime today = DateTime.Today;
                      int currentDay = today.Day;
                      int currentYear = today.Year;
                      int currentMonth = today.Month;
                      int age = 0;
                      if (currentMonth < month) {
                          age -= 1;
                      } else if (currentMonth == month) {
                          if (currentDay < day) {
                              age -= 1;
                          }
                      }
                      currentYear -= year;
                      age += currentYear;
                      return age;
                  }
                  public static void Main()
                  {
                      int ageInYears = getAge(8, 10, 2007);
                      Console.WriteLine(ageInYears);
                  }
              }
              

              有点混乱,但仔细看代码,就会明白了。

              【讨论】:

                【解决方案8】:

                我认为这个问题可以用像这样更简单的方法来解决-

                类可以是-

                using System;
                
                namespace TSA
                {
                    class BirthDay
                    {
                        double ageDay;
                        public BirthDay(int day, int month, int year)
                        {
                            DateTime birthDate = new DateTime(year, month, day);
                            ageDay = (birthDate - DateTime.Now).TotalDays; //DateTime.UtcNow
                        }
                
                        internal int GetAgeYear()
                        {
                            return (int)Math.Truncate(ageDay / 365);
                        }
                
                        internal int GetAgeMonth()
                        {
                            return (int)Math.Truncate((ageDay % 365) / 30);
                        }
                    }
                }
                

                电话可以像-

                BirthDay b = new BirthDay(1,12,1990);
                int year = b.GetAgeYear();
                int month = b.GetAgeMonth();
                

                【讨论】:

                  【解决方案9】:
                  int Age = new DateTime((DateTime.Now - BirthDate).Ticks).Year -1;
                  Console.WriteLine("Age {0}", Age);
                  

                  【讨论】:

                    【解决方案10】:

                    这是在一行中回答这个问题的最简单方法。

                    DateTime Dob = DateTime.Parse("1985-04-24");
                     
                    int Age = DateTime.MinValue.AddDays(DateTime.Now.Subtract(Dob).TotalHours/24 - 1).Year - 1;
                    

                    这也适用于闰年。

                    【讨论】:

                    • 你的答案错了一天,它会给出前一天的生日
                    【解决方案11】:

                    一个易于理解和简单的解决方案。

                    // Save today's date.
                    var today = DateTime.Today;
                    
                    // Calculate the age.
                    var age = today.Year - birthdate.Year;
                    
                    // Go back to the year in which the person was born in case of a leap year
                    if (birthdate.Date > today.AddYears(-age)) age--;
                    

                    但是,这假设您正在寻找时代的西方理念,而不是使用East Asian reckoning

                    【讨论】:

                    • 此答案不适用于所有语言环境和所有年龄段。包括俄罗斯(1918 年)、希腊(1924 年)和土耳其(1926 年)在内的几个国家已经跳过了当前活人出生后的日期。
                    • 其实还是不完全正确。此代码假定“bday”是 DateTime 的日期部分。这是一个极端情况(我想大多数人只会传递日期而不是日期时间),但是如果您将生日作为日期和时间传递,其中时间大于 00:00:00,那么您会遇到 Danvil 指出的错误。设置 bday = bday.Date 可以解决这个问题。
                    • 这是 12 年,但你为什么不直接减去 brithday - 今天以后去时间跨度,你可以在没有 if 的情况下得到它。
                    【解决方案12】:

                    这是一个非常适合我的函数。不用计算,很简单。

                        public static string ToAge(this DateTime dob, DateTime? toDate = null)
                        {
                            if (!toDate.HasValue)
                                toDate = DateTime.Now;
                            var now = toDate.Value;
                    
                            if (now.CompareTo(dob) < 0)
                                return "Future date";
                    
                            int years = now.Year - dob.Year;
                            int months = now.Month - dob.Month;
                            int days = now.Day - dob.Day;
                    
                            if (days < 0)
                            {
                                months--;
                                days = DateTime.DaysInMonth(dob.Year, dob.Month) - dob.Day + now.Day;
                            }
                    
                            if (months < 0)
                            {
                                years--;
                                months = 12 + months;
                            }
                    
                    
                            return string.Format("{0} year(s), {1} month(s), {2} days(s)",
                                years,
                                months,
                                days);
                        }
                    

                    这是一个单元测试:

                        [Test]
                        public void ToAgeTests()
                        {
                            var date = new DateTime(2000, 1, 1);
                            Assert.AreEqual("0 year(s), 0 month(s), 1 days(s)", new DateTime(1999, 12, 31).ToAge(date));
                            Assert.AreEqual("0 year(s), 0 month(s), 0 days(s)", new DateTime(2000, 1, 1).ToAge(date));
                            Assert.AreEqual("1 year(s), 0 month(s), 0 days(s)", new DateTime(1999, 1, 1).ToAge(date));
                            Assert.AreEqual("0 year(s), 11 month(s), 0 days(s)", new DateTime(1999, 2, 1).ToAge(date));
                            Assert.AreEqual("0 year(s), 10 month(s), 25 days(s)", new DateTime(1999, 2, 4).ToAge(date));
                            Assert.AreEqual("0 year(s), 10 month(s), 1 days(s)", new DateTime(1999, 2, 28).ToAge(date));
                    
                            date = new DateTime(2000, 2, 15);
                            Assert.AreEqual("0 year(s), 0 month(s), 28 days(s)", new DateTime(2000, 1, 18).ToAge(date));
                        }
                    

                    【讨论】:

                    • “没有计算”? ;/
                    【解决方案13】:

                    很简单的答案

                            DateTime dob = new DateTime(1991, 3, 4); 
                            DateTime now = DateTime.Now; 
                            int dobDay = dob.Day, dobMonth = dob.Month; 
                            int add = -1; 
                            if (dobMonth < now.Month)
                            {
                                add = 0;
                            }
                            else if (dobMonth == now.Month)
                            {
                                if(dobDay <= now.Day)
                                {
                                    add = 0;
                                }
                                else
                                {
                                    add = -1;
                                }
                            }
                            else
                            {
                                add = -1;
                            } 
                            int age = now.Year - dob.Year + add;
                    

                    【讨论】:

                    • 应该为 OP 以及未来的读者描述你的答案。
                    • 你的代码不简单,一团糟。我会写这个,也许你不相信,但下面的代码做同样的事情(现在 - dob)。年份
                    【解决方案14】:

                    由于闰年和一切,我所知道的最好方法是:

                    DateTime birthDate = new DateTime(2000,3,1);
                    int age = (int)Math.Floor((DateTime.Now - birthDate).TotalDays / 365.25D);
                    

                    【讨论】:

                    • Buggy,只是因为它不处理闰年/天。如果你在生日那天运行它,它会计算出一半的错误年龄。
                    【解决方案15】:

                    另一个功能,不是我做的,而是在网上找到并稍微改进了一下:

                    public static int GetAge(DateTime birthDate)
                    {
                        DateTime n = DateTime.Now; // To avoid a race condition around midnight
                        int age = n.Year - birthDate.Year;
                    
                        if (n.Month < birthDate.Month || (n.Month == birthDate.Month && n.Day < birthDate.Day))
                            age--;
                    
                        return age;
                    }
                    

                    我想到了两件事:来自不使用公历的国家的人呢? DateTime.Now 我认为是特定于服务器的文化。我对实际使用亚洲日历的知识绝对为零,我不知道是否有一种简单的方法可以在日历之间转换日期,但以防万一你想知道那些来自 4660 年的中国人:-)

                    【讨论】:

                    • 这似乎能最好地处理不同的区域(日期格式)。
                    【解决方案16】:

                    我的建议

                    int age = (int) ((DateTime.Now - bday).TotalDays/365.242199);
                    

                    这似乎是在正确的日期改变年份。 (我现场测试到 107 岁。)

                    【讨论】:

                    • 我认为 Harry Patch 不会欣赏您的现场测试方法:latimes.com/news/obituaries/…
                    • 谷歌说days in a year = 365.242199
                    • 公历一年的平均长度是365.2425天。
                    • 我想说,这是最简单的解决方案之一,它足够好。谁在乎我是否在我 X 岁生日前半天而程序说我 X 岁。该程序或多或少是正确的,尽管在数学上不是。我真的很喜欢这个解决方案。
                    • ^^ 因为有时它很重要。在我的测试中,这在人的生日失败,它报告他们比他们年轻。
                    【解决方案17】:

                    这是一个单行:

                    int age = new DateTime(DateTime.Now.Subtract(birthday).Ticks).Year-1;
                    

                    【讨论】:

                    • 这个坏了。可测试: public static int CalculateAge(DateTime dateOfBirth, DateTime dateToCalculateAge) { return new DateTime(dateToCalculateAge.Subtract(dateOfBirth).Ticks).Year - 1; ...当我输入 1990-06-01 并计算他 14 岁生日 (1990-05-31) 前一天的年龄时给出 14 岁。
                    • @Kjensen 一天班是由实时范围(dateOfBirth 到 dateToCalculateAge)和 DateTime.Substract 创建的时间范围内 29 日 FEB 的不同计数引起的,它总是隐式地与 DateTime 进行比较。最小,即 1-JAN-0001。从 1990 年 5 月 31 日到 2005 年 6 月 1 日,您有四个这样的闰日,从 0001 年 1 月 1 日到 0015 年 1 月 1 日,您只有三个 29 日。
                    【解决方案18】:

                    这是一个测试sn-p:

                    DateTime bDay = new DateTime(2000, 2, 29);
                    DateTime now = new DateTime(2009, 2, 28);
                    MessageBox.Show(string.Format("Test {0} {1} {2}",
                                    CalculateAgeWrong1(bDay, now),      // outputs 9
                                    CalculateAgeWrong2(bDay, now),      // outputs 9
                                    CalculateAgeCorrect(bDay, now),     // outputs 8
                                    CalculateAgeCorrect2(bDay, now)));  // outputs 8
                    

                    这里有方法:

                    public int CalculateAgeWrong1(DateTime birthDate, DateTime now)
                    {
                        return new DateTime(now.Subtract(birthDate).Ticks).Year - 1;
                    }
                    
                    public int CalculateAgeWrong2(DateTime birthDate, DateTime now)
                    {
                        int age = now.Year - birthDate.Year;
                    
                        if (now < birthDate.AddYears(age))
                            age--;
                    
                        return age;
                    }
                    
                    public int CalculateAgeCorrect(DateTime birthDate, DateTime now)
                    {
                        int age = now.Year - birthDate.Year;
                    
                        if (now.Month < birthDate.Month || (now.Month == birthDate.Month && now.Day < birthDate.Day))
                            age--;
                    
                        return age;
                    }
                    
                    public int CalculateAgeCorrect2(DateTime birthDate, DateTime now)
                    {
                        int age = now.Year - birthDate.Year;
                    
                        // For leap years we need this
                        if (birthDate > now.AddYears(-age)) 
                            age--;
                        // Don't use:
                        // if (birthDate.AddYears(age) > now) 
                        //     age--;
                    
                        return age;
                    }
                    

                    【讨论】:

                    • 虽然此代码有效,但它断言出生于闰日的人在非闰年的 3 月 1 日而不是 2 月 28 日达到下一年的年龄。实际上,任何一个选项都可能是正确的Wikipedia has something to say about this。因此,虽然您的代码没有“错误”,但公认的解决方案也不是。
                    • @MattJohnson 我认为这实际上是正确的。如果我的生日是 2 月 29 日,那么 2 月 28 日我的生日还没有过去,我应该仍然是 2 月 27 日的年龄。但是,3 月 1 日,我们已经过了我的生日,我应该是下一个年龄。在美国,一家销售酒类的企业会有一个标语,上面写着“如果你在 YYYY 的这一天之后出生,你就不能购买酒类”(YYYY 每年都在变化)。这意味着 2 月 29 日出生的人在 21 岁那年(大多数地方)不能在 2 月 28 日买酒,并且支持他们在 3 月 1 日之前不会大一岁的想法。
                    • @jfren484 - 阅读维基百科的文章。不同的司法管辖区差异很大。
                    • @jfren484 你的说法与哲学完全无关;但一切都与你自己的个人感觉有关。 2 月 29 日出生的人“年龄”在很大程度上并不重要,除非年龄构成“法定年龄界限”(例如,可以买酒、投票、领取养老金、参军、获得驾驶执照)。考虑美国的饮酒年龄(21 岁):对于大多数人来说是 7670 天。闰年 2 月 29 日之前或闰年 3 月 1 日之前出生的是 7671 天。如果出生于 2 月 29 日:2 月 28 日为 7670 天,3 月 1 日为 7671 天。 选择是任意的它可以任意选择。
                    • @CraigYoung 你不明白我在哲学上的意思。我用这个词作为与法律的对比。如果一个人正在编写一个需要知道一个人的法定年龄的应用程序,那么他们只需要知道他们的应用程序用于/用于如何对待 2 月 29 日出生的人的法律管辖区。但是,如果我们是谈论应该如何对待应该,那么这就是哲学的定义。是的,我给出的观点是我自己的观点,但正如我所说,我认为 3 月 1 日的争论比 2 月 28 日的争论更容易。
                    【解决方案19】:

                    这可能有效:

                    public override bool IsValid(DateTime value)
                    {
                        _dateOfBirth =  value;
                        var yearsOld = (double) (DateTime.Now.Subtract(_dateOfBirth).TotalDays/365);
                        if (yearsOld > 18)
                            return true;
                        return false;
                    }
                    

                    【讨论】:

                    • 哇。为什么 value 是对象而不是 DateTime?方法签名应该是public override bool Is18OrOlder(DateTime birthday) 2月29日出生的人呢?谁说我们要检查用户是否至少 18 岁?问题是“我如何计算某人的年龄?”
                    • 这是怎么发生的?我什至不记得将 IsValid 作为对象。应该是日期时间!
                    • 为什么不使用if 语句,而不是return yearsOld &gt; 18;
                    【解决方案20】:

                    为什么 MSDN 的帮助没有告诉你呢?看起来很明显:

                    System.DateTime birthTime = AskTheUser(myUser); // :-)
                    System.DateTime now = System.DateTime.Now;
                    System.TimeSpan age = now - birthTime; // As simple as that
                    double ageInDays = age.TotalDays; // Will you convert to whatever you want yourself?
                    

                    【讨论】:

                    • 好吧,如果您身处地球上成年人年龄以天为单位的零个国家之一,那真是太棒了。
                    【解决方案21】:

                    由于转换次数和 UtcNow 较少,此代码可以照顾在闰年 2 月 29 日出生的人:

                    public int GetAge(DateTime DateOfBirth)
                    {
                        var Now = DateTime.UtcNow;
                        return Now.Year - DateOfBirth.Year -
                            (
                                (
                                    Now.Month > DateOfBirth.Month ||
                                    (Now.Month == DateOfBirth.Month && Now.Day >= DateOfBirth.Day)
                                ) ? 0 : 1
                            );
                    }
                    

                    【讨论】:

                    • 就是今天! (下一个是四年后。)
                    【解决方案22】:

                    单行答案:

                    DateTime dateOfBirth = Convert.ToDateTime("01/16/1990");
                    var age = ((DateTime.Now - dateOfBirth).Days) / 365;
                    

                    【讨论】:

                    • 闰年呢?
                    【解决方案23】:

                    与 2 月 28 日相比,这是能够解决 2 月 29 日生日的最准确答案之一。

                    public int GetAge(DateTime birthDate)
                    {
                        int age = DateTime.Now.Year - birthDate.Year;
                    
                        if (birthDate.DayOfYear > DateTime.Now.DayOfYear)
                            age--;
                    
                        return age;
                    }
                    
                    
                    
                    
                    

                    【讨论】:

                    • 就是今天! (下一个是四年后。)
                    • 你可以使用 DateTime.Today 代替,因为时间对于计算并不重要
                    【解决方案24】:

                    可以这么简单:

                    int age = DateTime.Now.AddTicks(0 - dob.Ticks).Year - 1;
                    

                    【讨论】:

                      【解决方案25】:

                      我在这个问题上使用了以下内容。我知道它不是很优雅,但它正在工作。

                      DateTime zeroTime = new DateTime(1, 1, 1);
                      var date1 = new DateTime(1983, 03, 04);
                      var date2 = DateTime.Now;
                      var dif = date2 - date1;
                      int years = (zeroTime + dif).Year - 1;
                      Log.DebugFormat("Years -->{0}", years);
                      

                      【讨论】:

                        【解决方案26】:

                        哇,我不得不在这里给出我的答案......这么简单的问题有很多答案。

                        private int CalcularIdade(DateTime dtNascimento)
                            {
                                var nHoje = Convert.ToInt32(DateTime.Today.ToString("yyyyMMdd"));
                                var nAniversario = Convert.ToInt32(dtNascimento.ToString("yyyyMMdd"));
                        
                                double diff = (nHoje - nAniversario) / 10000;
                        
                                var ret = Convert.ToInt32(Math.Truncate(diff));
                        
                                return ret;
                            }
                        

                        【讨论】:

                          【解决方案27】:

                          我经常数数我的手指。当事情发生变化时,我需要查看日历来确定。所以这就是我在我的代码中所做的:

                          int AgeNow(DateTime birthday)
                          {
                              return AgeAt(DateTime.Now, birthday);
                          }
                          
                          int AgeAt(DateTime now, DateTime birthday)
                          {
                              return AgeAt(now, birthday, CultureInfo.CurrentCulture.Calendar);
                          }
                          
                          int AgeAt(DateTime now, DateTime birthday, Calendar calendar)
                          {
                              // My age has increased on the morning of my
                              // birthday even though I was born in the evening.
                              now = now.Date;
                              birthday = birthday.Date;
                          
                              var age = 0;
                              if (now <= birthday) return age; // I am zero now if I am to be born tomorrow.
                          
                              while (calendar.AddYears(birthday, age + 1) <= now)
                              {
                                  age++;
                              }
                              return age;
                          }
                          

                          LINQPad 中运行它会得到:

                          PASSED: someone born on 28 February 1964 is age 4 on 28 February 1968
                          PASSED: someone born on 29 February 1964 is age 3 on 28 February 1968
                          PASSED: someone born on 31 December 2016 is age 0 on 01 January 2017
                          

                          LINQPad 中的代码是here

                          【讨论】:

                            【解决方案28】:

                            看看这个:

                            TimeSpan ts = DateTime.Now.Subtract(Birthdate);
                            age = (byte)(ts.TotalDays / 365.25);
                            

                            【讨论】:

                              【解决方案29】:

                              要计算一个人的年龄,

                              DateTime dateOfBirth;
                              
                              int ageInYears = DateTime.Now.Year - dateOfBirth.Year;
                              
                              if (dateOfBirth > today.AddYears(-ageInYears )) ageInYears --;
                              

                              【讨论】:

                              • 你刚刚复制了第一个答案,Patel 得到了什么?
                              【解决方案30】:

                              我会这样做:

                              DateTime birthDay = new DateTime(1990, 05, 23);
                              DateTime age = DateTime.Now - birthDay;
                              

                              通过这种方式,您可以计算一个人的确切年龄,如果需要,可以精确到毫秒。

                              【讨论】:

                              • 错了。在您的代码时代将是一个 TimeSpan。不是日期时间。
                              • 问题在于,像“17 岁”这样的年龄并不能直接转换为 TimeSpan,因为您不知道这 17 年中的哪一年是闰年。
                              猜你喜欢
                              • 1970-01-01
                              • 2023-03-14
                              • 2013-10-31
                              • 1970-01-01
                              • 1970-01-01
                              • 2018-10-17
                              • 1970-01-01
                              • 2014-04-04
                              • 2010-11-10
                              相关资源
                              最近更新 更多