如何计算C#中某人的年龄?
给定一个代表一个人生日的" DateTime",我如何计算他们的年龄(以岁为单位)?
解决方案:
许多年前,为了在我的网站上提供年龄计算器的,头,我编写了一个函数来计算年龄的一小部分。这是该函数到C(从PHP版本开始)的快速移植。恐怕我还无法测试Cversion,但希望我们一切都一样!
(诚然,为了在Stack Overflow上显示用户个人资料,这有点花哨,但也许读者会发现一些用处。:-)
double AgeDiff(DateTime date1, DateTime date2) { double years = date2.Year - date1.Year; /* * If date2 and date1 + round(date2 - date1) are on different sides * of 29 February, then our partial year is considered to have 366 * days total, otherwise it's 365. Note that 59 is the day number * of 29 Feb. */ double fraction = 365 + (DateTime.IsLeapYear(date2.Year) && date2.DayOfYear >= 59 && (date1.DayOfYear < 59 || date1.DayOfYear > date2.DayOfYear) ? 1 : 0); /* * The only really nontrivial case is if date1 is in a leap year, * and date2 is not. So let's handle the others first. */ if (DateTime.IsLeapYear(date2.Year) == DateTime.IsLeapYear(date1.Year)) return years + (date2.DayOfYear - date1.DayOfYear) / fraction; /* * If date2 is in a leap year, but date1 is not and is March or * beyond, shift up by a day. */ if (DateTime.IsLeapYear(date2.Year)) { return years + (date2.DayOfYear - date1.DayOfYear - (date1.DayOfYear >= 59 ? 1 : 0)) / fraction; } /* * If date1 is not on 29 February, shift down date1 by a day if * March or later. Proceed normally. */ if (date1.DayOfYear != 59) { return years + (date2.DayOfYear - date1.DayOfYear + (date1.DayOfYear > 59 ? 1 : 0)) / fraction; } /* * Okay, here date1 is on 29 February, and date2 is not on a leap * year. What to do now? On 28 Feb in date2's year, the ``age'' * should be just shy of a whole number, and on 1 Mar should be * just over. Perhaps the easiest way is to a point halfway * between those two: 58.5. */ return years + (date2.DayOfYear - 58.5) / fraction; }
由于leap年和一切,我知道的最好方法是:
DateTime birthDate = new DateTime(2000,3,1); int age = (int)Math.Floor((DateTime.Now - birthDate).TotalDays / 365.25D);
希望这可以帮助。
另一个功能,不是我所为,而是在网络上找到并进行了一些改进:
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年的中国人:-)
一个易于理解和简单的## 解决方案。
// Save today's date. var today = DateTime.Today; // Calculate the age. var age = today.Year - birthdate.Year; // Go back to the year the person was born in case of a leap year if (birthdate > today.AddYears(-age)) age--;
但是,这假设我们正在寻找西方的年龄观念,而不是使用东亚估算。
这是我们在这里使用的版本。它有效,而且非常简单。这与Jeff的想法相同,但我认为它更清楚一点,因为它分离出了减法逻辑,因此更容易理解。
public static int GetAge(this DateTime dateOfBirth, DateTime dateAsAt) { return dateAsAt.Year - dateOfBirth.Year - (dateOfBirth.DayOfYear < dateAsAt.DayOfYear ? 0 : 1); }
如果我们认为这类事情不清楚,可以扩展三元运算符以使其更加清晰。
显然,这是作为" DateTime"上的扩展方法完成的,但是显然,我们可以抓住完成工作的那一行代码,并将其放置在任何地方。这里,为了完整性起见,我们在DateTime.Now
中传入了扩展方法的另一个重载。
这是一种奇怪的方法,但是如果我们将日期格式设置为yyyymmdd
并从当前日期中减去出生日期,然后删除年龄的最后4位数字:)
我不懂C#,但是我相信这可以使用任何语言。
20080814 - 19800703 = 280111
删除最后4位数字= 28.
CCode:
int now = int.Parse(DateTime.Now.ToString("yyyyMMdd")); int dob = int.Parse(dateOfBirth.ToString("yyyyMMdd")); int age = (now - dob) / 10000;
或者,也可以不使用扩展方法形式的所有类型转换。错误检查省略:
public static Int32 GetAge(this DateTime dateOfBirth) { var today = DateTime.Today; var a = (today.Year * 100 + today.Month) * 100 + today.Day; var b = (dateOfBirth.Year * 100 + dateOfBirth.Month) * 100 + dateOfBirth.Day; return (a - b) / 10000; }
我认为到目前为止,没有任何答案提供不同的年龄计算文化。例如,参见东亚年龄估算与西方国家的估算。
任何真正的答案都必须包括本地化。在此示例中,策略模式可能是有序的。
我创建了一个SQL Server用户定义函数来计算某人的年龄(给定生日)。当我们需要将其作为查询的一部分时,这很有用:
using System; using System.Data; using System.Data.Sql; using System.Data.SqlClient; using System.Data.SqlTypes; using Microsoft.SqlServer.Server; public partial class UserDefinedFunctions { [SqlFunction(DataAccess = DataAccessKind.Read)] public static SqlInt32 CalculateAge(string strBirthDate) { DateTime dtBirthDate = new DateTime(); dtBirthDate = Convert.ToDateTime(strBirthDate); DateTime dtToday = DateTime.Now; // get the difference in years int years = dtToday.Year - dtBirthDate.Year; // subtract another year if we're before the // birth day in the current year if (dtToday.Month < dtBirthDate.Month || (dtToday.Month == dtBirthDate.Month && dtToday.Day < dtBirthDate.Day)) years=years-1; int intCustomerAge = years; return intCustomerAge; } };
我认为TimeSpan包含了我们所需的全部内容,而不必求助于365.25(或者任何其他近似值)。在8月的示例中进行扩展:
DateTime myBD = new DateTime(1980, 10, 10); TimeSpan difference = DateTime.Now.Subtract(myBD); textBox1.Text = difference.Years + " years " + difference.Months + " Months " + difference.Days + " days";
我的建议
int age = (int) ((DateTime.Now - bday).TotalDays/365.242199);
似乎在正确的日期更改了年份。 (我现场测试到107岁)
我花了一些时间来研究这个问题,并想出这个问题来计算某人的年龄(年,月,日)。我已针对2月29日的问题和leap年进行了测试,它似乎可以正常工作,感谢任何反馈:
public void LoopAge(DateTime myDOB, DateTime FutureDate) { int years = 0; int months = 0; int days = 0; DateTime tmpMyDOB = new DateTime(myDOB.Year, myDOB.Month, 1); DateTime tmpFutureDate = new DateTime(FutureDate.Year, FutureDate.Month, 1); while (tmpMyDOB.AddYears(years).AddMonths(months) < tmpFutureDate) { months++; if (months > 12) { years++; months = months - 12; } } if (FutureDate.Day >= myDOB.Day) { days = days + FutureDate.Day - myDOB.Day; } else { months--; if (months < 0) { years--; months = months + 12; } days += DateTime.DaysInMonth( FutureDate.AddMonths(-1).Year, FutureDate.AddMonths(-1).Month ) + FutureDate.Day - myDOB.Day; } //add an extra day if the dob is a leap day if (DateTime.IsLeapYear(myDOB.Year) && myDOB.Month == 2 && myDOB.Day == 29) { //but only if the future date is less than 1st March if (FutureDate >= new DateTime(FutureDate.Year, 3, 1)) days++; } }
我参加晚会很晚,但是这里有一条线:
int age = new DateTime(DateTime.Now.Subtract(birthday).Ticks).Year-1;
这是一个## 解决方案。
DateTime dateOfBirth = new DateTime(2000, 4, 18); DateTime currentDate = DateTime.Now; int ageInYears = 0; int ageInMonths = 0; int ageInDays = 0; ageInDays = currentDate.Day - dateOfBirth.Day; ageInMonths = currentDate.Month - dateOfBirth.Month; ageInYears = currentDate.Year - dateOfBirth.Year; if (ageInDays < 0) { ageInDays += DateTime.DaysInMonth(currentDate.Year, currentDate.Month); ageInMonths = ageInMonths--; if (ageInMonths < 0) { ageInMonths += 12; ageInYears--; } } if (ageInMonths < 0) { ageInMonths += 12; ageInYears--; } Console.WriteLine("{0}, {1}, {2}", ageInYears, ageInMonths, ageInDays);
我不知道如何接受错误的## 解决方案。
正确的摘录由Michael Stum撰写
这是一个测试代码段:
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
这里有方法:
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 override bool IsValid(DateTime value) { _dateOfBirth = value; var yearsOld = (double) (DateTime.Now.Subtract(_dateOfBirth).TotalDays/365); if (yearsOld > 18) return true; return false; }
我创建了一个年龄结构,如下所示:
public struct Age : IEquatable<Age>, IComparable<Age> { private readonly int _years; private readonly int _months; private readonly int _days; public int Years { get { return _years; } } public int Months { get { return _months; } } public int Days { get { return _days; } } public Age( int years, int months, int days ) : this() { _years = years; _months = months; _days = days; } public static Age CalculateAge( DateTime dateOfBirth, DateTime date ) { // Here is some logic that ressembles Mike's solution, although it // also takes into account months & days. // Ommitted for brevity. return new Age (years, months, days); } // Ommited Equality, Comparable, GetHashCode, functionality for brevity. }
这是CI的一些小代码示例,请注意在特殊情况下(特别是leap年)的边缘情况,并非以上所有## 解决方案都将它们考虑在内。将答案作为DateTime推出可能会导致问题,因为我们最终可能会尝试在特定月份中放置太多天,例如2月30天
public string LoopAge(DateTime myDOB, DateTime FutureDate) { int years = 0; int months = 0; int days = 0; DateTime tmpMyDOB = new DateTime(myDOB.Year, myDOB.Month, 1); DateTime tmpFutureDate = new DateTime(FutureDate.Year, FutureDate.Month, 1); while (tmpMyDOB.AddYears(years).AddMonths(months) < tmpFutureDate) { months++; if (months > 12) { years++; months = months - 12; } } if (FutureDate.Day >= myDOB.Day) { days = days + FutureDate.Day - myDOB.Day; } else { months--; if (months < 0) { years--; months = months + 12; } days = days + (DateTime.DaysInMonth(FutureDate.AddMonths(-1).Year, FutureDate.AddMonths(-1).Month) + FutureDate.Day) - myDOB.Day; } //add an extra day if the dob is a leap day if (DateTime.IsLeapYear(myDOB.Year) && myDOB.Month == 2 && myDOB.Day == 29) { //but only if the future date is less than 1st March if(FutureDate >= new DateTime(FutureDate.Year, 3,1)) days++; } return "Years: " + years + " Months: " + months + " Days: " + days; }
我用这个:
public static class DateTimeExtensions { public static int Age(this DateTime birthDate) { return Age(birthDate, DateTime.Now); } public static int Age(this DateTime birthDate, DateTime offsetDate) { int result=0; result = offsetDate.Year - birthDate.Year; if (offsetDate.DayOfYear < birthDate.DayOfYear) { result--; } return result; } }
保持简单(可能很愚蠢:)。
DateTime birth = new DateTime(1975, 09, 27, 01, 00, 00, 00); TimeSpan ts = DateTime.Now - birth; Console.WriteLine("You are approximately " + ts.TotalSeconds.ToString() + " seconds old.");
private int GetAge(int _year, int _month, int _day { DateTime yourBirthDate= new DateTime(_year, _month, _day); DateTime todaysDateTime = DateTime.Today; int noOfYears = todaysDateTime.Year - yourBirthDate.Year; if (DateTime.Now.Month < yourBirthDate.Month || (DateTime.Now.Month == yourBirthDate.Month && DateTime.Now.Day < yourBirthDate.Day)) { noOfYears--; } return noOfYears; }
我发现过的最简单的方法就是这个。它适用于美国和西欧的语言环境。不能和其他地方说话,尤其是像中国这样的地方。最初计算年龄后,最多最多有4个比较。
public int AgeInYears(DateTime birthDate, DateTime referenceDate) { Debug.Assert(referenceDate >= birthDate, "birth date must be on or prior to the reference date"); DateTime birth = birthDate.Date; DateTime reference = referenceDate.Date; int years = (reference.Year - birth.Year); // // an offset of -1 is applied if the birth date has // not yet occurred in the current year. // if (reference.Month > birth.Month); else if (reference.Month < birth.Month) --years; else // in birth month { if (reference.Day < birth.Day) --years; } return years ; }
我一直在寻找答案,发现没有人提到leap日出生的法规/法律含义。例如,根据Wikipedia,如果我们于2月29日出生在各个司法管辖区,那么非-年生日会有所不同:
在英国和香港:这是一年中的第几天,因此第二天3月1日是生日。在新西兰:这是前一天,即2月28日用于驾驶员执照发放,3月1日用于其他目的。台湾:2月28日。
据我所知,在美国,成文法对此事保持沉默,这取决于普通法以及各种监管机构如何在其法规中定义事物。
为此,需要进行以下改进:
public enum LeapDayRule { OrdinalDay = 1 , LastDayOfMonth = 2 , } static int ComputeAgeInYears(DateTime birth, DateTime reference, LeapYearBirthdayRule ruleInEffect) { bool isLeapYearBirthday = CultureInfo.CurrentCulture.Calendar.IsLeapDay(birth.Year, birth.Month, birth.Day); DateTime cutoff; if (isLeapYearBirthday && !DateTime.IsLeapYear(reference.Year)) { switch (ruleInEffect) { case LeapDayRule.OrdinalDay: cutoff = new DateTime(reference.Year, 1, 1) .AddDays(birth.DayOfYear - 1); break; case LeapDayRule.LastDayOfMonth: cutoff = new DateTime(reference.Year, birth.Month, 1) .AddMonths(1) .AddDays(-1); break; default: throw new InvalidOperationException(); } } else { cutoff = new DateTime(reference.Year, birth.Month, birth.Day); } int age = (reference.Year - birth.Year) + (reference >= cutoff ? 0 : -1); return age < 0 ? 0 : age; }
应该注意的是,该代码假定:
西方(欧洲)对年龄的估算,以及A日历,如公历在月末插入一个the日。