如何计算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日。

