Как вычислить чей-то возраст в C#?
дали DateTime
представляя день рождения человека, как я могу рассчитать их возраст в годах?
30 ответов
легко понять и простое решение.
// 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--;
однако, это предполагает, что вы ищете западный идея возраста и не использовать Восточно-Азиатских расплаты.
Это странный способ сделать это, но если вы форматируете дату yyyymmdd
и вычесть дату рождения из текущей даты, а затем отбросить последние 4 цифры у вас есть возраст:)
Я не знаю C#, но я считаю, что это будет работать на любом языке.
20080814 - 19800703 = 280111
отбросьте последние 4 цифры = 28
.
C# Код:
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;
}
Я не знаю, как можно принять неправильное решение. Правильный фрагмент C# был написан Майклом 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;
}
Я не думаю, что любой из ответов до сих пор обеспечивает культуры, которые вычисляют возраст по-разному. См., например, Восточно-Азиатская Возрастная Оценка против того, что на Западе.
любой реальные ответ должен включать локализации. The Шаблон Стратегии вероятно, будет в порядке в этом примере.
простой ответ на это-применить AddYears
как показано ниже, потому что это единственный собственный метод для добавления лет к 29 февраля. из високосных лет и получить правильный результат от 28 февраля. для обычных лет.
некоторые чувствуют, что 1 марта. это день рождения leaplings, но ни .Net, ни какое-либо официальное правило не поддерживает это, ни общая логика не объясняет, почему некоторые рожденные в феврале должны иметь 75% своих дней рождения в другом месяце.
далее, возраст метод поддается добавлению в качестве расширения в DateTime
. Таким образом, вы можете получить возраст самым простым способом:
- элемент списка
int возраст = дата рождения.Возраст();
public static class DateTimeExtensions
{
/// <summary>
/// Calculates the age in years of the current System.DateTime object today.
/// </summary>
/// <param name="birthDate">The date of birth</param>
/// <returns>Age in years today. 0 is returned for a future date of birth.</returns>
public static int Age(this DateTime birthDate)
{
return Age(birthDate, DateTime.Today);
}
/// <summary>
/// Calculates the age in years of the current System.DateTime object on a later date.
/// </summary>
/// <param name="birthDate">The date of birth</param>
/// <param name="laterDate">The date on which to calculate the age.</param>
/// <returns>Age in years on a later day. 0 is returned as minimum.</returns>
public static int Age(this DateTime birthDate, DateTime laterDate)
{
int age;
age = laterDate.Year - birthDate.Year;
if (age > 0)
{
age -= Convert.ToInt32(laterDate.Date < birthDate.Date.AddYears(age));
}
else
{
age = 0;
}
return age;
}
}
Теперь запустите этот тест:
class Program
{
static void Main(string[] args)
{
RunTest();
}
private static void RunTest()
{
DateTime birthDate = new DateTime(2000, 2, 28);
DateTime laterDate = new DateTime(2011, 2, 27);
string iso = "yyyy-MM-dd";
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
Console.WriteLine("Birth date: " + birthDate.AddDays(i).ToString(iso) + " Later date: " + laterDate.AddDays(j).ToString(iso) + " Age: " + birthDate.AddDays(i).Age(laterDate.AddDays(j)).ToString());
}
}
Console.ReadKey();
}
}
пример критической даты таков:
дата рождения: 2000-02-29 позже дата: 2011-02-28 Возраст: 11
выход:
{
Birth date: 2000-02-28 Later date: 2011-02-27 Age: 10
Birth date: 2000-02-28 Later date: 2011-02-28 Age: 11
Birth date: 2000-02-28 Later date: 2011-03-01 Age: 11
Birth date: 2000-02-29 Later date: 2011-02-27 Age: 10
Birth date: 2000-02-29 Later date: 2011-02-28 Age: 11
Birth date: 2000-02-29 Later date: 2011-03-01 Age: 11
Birth date: 2000-03-01 Later date: 2011-02-27 Age: 10
Birth date: 2000-03-01 Later date: 2011-02-28 Age: 10
Birth date: 2000-03-01 Later date: 2011-03-01 Age: 11
}
и для более поздняя дата 2012-02-28:
{
Birth date: 2000-02-28 Later date: 2012-02-28 Age: 12
Birth date: 2000-02-28 Later date: 2012-02-29 Age: 12
Birth date: 2000-02-28 Later date: 2012-03-01 Age: 12
Birth date: 2000-02-29 Later date: 2012-02-28 Age: 11
Birth date: 2000-02-29 Later date: 2012-02-29 Age: 12
Birth date: 2000-02-29 Later date: 2012-03-01 Age: 12
Birth date: 2000-03-01 Later date: 2012-02-28 Age: 11
Birth date: 2000-03-01 Later date: 2012-02-29 Age: 11
Birth date: 2000-03-01 Later date: 2012-03-01 Age: 12
}
мое предложение
int age = (int) ((DateTime.Now - bday).TotalDays/365.242199);
Кажется, что год меняется на правильную дату. (Я тестируюсь до 107 лет)
другая функция, не мной, но найденная в интернете и немного доработанная:
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.Теперь в серверной культуре, я думаю. У меня есть абсолютно 0 знаний о работе с азиатскими календарями, и я не знаю, есть ли простой способ конвертировать даты между календарями, но на всякий случай вам интересно узнать об этих китайских парнях из 4660 год :-)
Я опаздываю на вечеринку, но вот одна строчка:
int age = new DateTime(DateTime.Now.Subtract(birthday).Ticks).Year-1;
2 основные проблемы для решения:
1. Рассчитать точный возраст - в годах, месяцах, днях и т. д.
2. Расчета, как правило, воспринимается возраст - люди обычно не заботятся, сколько им лет, они просто заботятся, когда их день рождения в текущем году.
решение 1 очевиден:
DateTime birth = DateTime.Parse("1.1.2000");
DateTime today = DateTime.Today; //we usually don't care about birth time
TimeSpan age = today - birth; //.NET FCL should guarantee this as precise
double ageInDays = age.TotalDays; //total number of days ... also precise
double daysInYear = 365.2425; //statistical value for 400 years
double ageInYears = ageInDays / daysInYear; //can be shifted ... not so precise
решение 2 это тот, который не так точен в определении общий возраст, но воспринимается людьми как точный. Люди также обычно используют его, когда они вычисляют свой возраст "вручную":
DateTime birth = DateTime.Parse("1.1.2000");
DateTime today = DateTime.Today;
int age = today.Year - birth.Year; //people perceive their age in years
if (today.Month < birth.Month ||
((today.Month == birth.Month) && (today.Day < birth.Day)))
{
age--; //birthday in current year not yet reached, we are 1 year younger ;)
//+ no birthday for 29.2. guys ... sorry, just wrong date for birth
}
примечания к 2.:
- это мое предпочтительное решение
- мы не можем использовать DateTime.DayOfYear или промежутки времени, как они сдвигают количество дней в високосные годы
- я поставил там немного больше строк для удобочитаемости
еще одна нота ... Я бы создал 2 статических перегруженных метода для него, для универсального использования, второй для использования-удобство:
public static int GetAge(DateTime bithDay, DateTime today)
{
//chosen solution method body
}
public static int GetAge(DateTime birthDay)
{
return GetAge(birthDay, DateTime.Now);
}
много лет назад, чтобы предоставить возраст калькулятор диковинкой на моем веб-сайте я написал функцию для вычисления возраста до дроби. Это быстрый порт этой функции на C# (от версия PHP). Боюсь, я не смог протестировать версию C#, но надеюсь, вам все равно понравится!
(по общему признанию, это немного трюк для целей отображения профилей пользователей при переполнении стека, но, возможно, читатели найдут для него какое-то применение. : -))
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;
}
Это версия, которую мы используем здесь. Это работает, и это довольно просто. Это та же идея, что и у Джеффа, но я думаю, что она немного яснее, потому что она разделяет логику вычитания, поэтому ее немного легче понять.
public static int GetAge(this DateTime dateOfBirth, DateTime dateAsAt)
{
return dateAsAt.Year - dateOfBirth.Year - (dateOfBirth.DayOfYear < dateAsAt.DayOfYear ? 0 : 1);
}
вы можете расширить тернарный оператор, чтобы сделать его еще более ясным, если вы думаете, что такого рода вещи неясны.
очевидно, что это делается как метод расширения на DateTime
, но ясно, что вы можете захватить эту одну строку кода, которая делает работу и кладет ее куда угодно. Здесь у нас есть еще одна перегрузка метода расширения, которая проходит в DateTime.Now
, просто для полноты.
Я использую этот:
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 birthDate = new DateTime(2000,3,1);
int age = (int)Math.Floor((DateTime.Now - birthDate).TotalDays / 365.25D);
надеюсь, что это помогает.
Это дает "более подробную информацию" к этому вопросу. Может быть, это то, что вы ищете
DateTime birth = new DateTime(1974, 8, 29);
DateTime today = DateTime.Now;
TimeSpan span = today - birth;
DateTime age = DateTime.MinValue + span;
// Make adjustment due to MinValue equalling 1/1/1
int years = age.Year - 1;
int months = age.Month - 1;
int days = age.Day - 1;
// Print out not only how many years old they are but give months and days as well
Console.Write("{0} years, {1} months, {2} days", years, months, days);
Я создал пользовательскую функцию 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;
}
};
Я провел некоторое время, работая над этим и придумал это, чтобы вычислить чей-то возраст в годах, месяцах и днях. Я протестировал против проблемы 29 февраля и високосных лет, и, похоже, это работает, я был бы признателен за любую обратную связь:
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++;
}
}
вот еще один ответ:
public static int AgeInYears(DateTime birthday, DateTime today)
{
return ((today.Year - birthday.Year) * 372 + (today.Month - birthday.Month) * 31 + (today.Day - birthday.Day)) / 372;
}
это было обширно блок-испытано. Это выглядит немного "волшебно". Число 372 - это количество дней, которое было бы в году, если бы каждый месяц имел 31 день.
объяснение, почему он работает (поднял отсюда) составляет:
давайте
Yn = DateTime.Now.Year, Yb = birthday.Year, Mn = DateTime.Now.Month, Mb = birthday.Month, Dn = DateTime.Now.Day, Db = birthday.Day
age = Yn - Yb + (31*(Mn - Mb) + (Dn - Db)) / 372
мы знаем, что нам нужно либо
Yn-Yb
если дата уже была дошло,Yn-Yb-1
если это не имеет.a) если
Mn<Mb
, мы-341 <= 31*(Mn-Mb) <= -31 and -30 <= Dn-Db <= 30
-371 <= 31*(Mn - Mb) + (Dn - Db) <= -1
с целочисленным делением
(31*(Mn - Mb) + (Dn - Db)) / 372 = -1
b) Если
Mn=Mb
иDn<Db
, мы31*(Mn - Mb) = 0 and -30 <= Dn-Db <= -1
с целочисленным делением, снова
(31*(Mn - Mb) + (Dn - Db)) / 372 = -1
c) если
Mn>Mb
, мы31 <= 31*(Mn-Mb) <= 341 and -30 <= Dn-Db <= 30
1 <= 31*(Mn - Mb) + (Dn - Db) <= 371
с целочисленным делением
(31*(Mn - Mb) + (Dn - Db)) / 372 = 0
d) Если
Mn=Mb
иDn>Db
, мы31*(Mn - Mb) = 0 and 1 <= Dn-Db <= 3
0с целочисленным делением, снова
(31*(Mn - Mb) + (Dn - Db)) / 372 = 0
e) если
Mn=Mb
иDn=Db
, мы31*(Mn - Mb) + Dn-Db = 0
и поэтому
(31*(Mn - Mb) + (Dn - Db)) / 372 = 0
сохранить его простым (и, возможно, глупый:)).
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.");
TimeSpan diff = DateTime.Now - birthdayDateTime;
string age = String.Format("{0:%y} years, {0:%M} months, {0:%d}, days old", diff);
Я не уверен, как именно вы хотите, чтобы он вернулся к вам, поэтому я просто сделал читаемую строку.
нужно ли рассматривать людей, которые меньше 1 года? как китайская культура, мы описываем возраст маленьких детей как 2 месяца или 4 недели.
ниже моя реализация, это не так просто, как я себе представлял, особенно иметь дело с датой, как 2/28.
public static string HowOld(DateTime birthday, DateTime now)
{
if (now < birthday)
throw new ArgumentOutOfRangeException("birthday must be less than now.");
TimeSpan diff = now - birthday;
int diffDays = (int)diff.TotalDays;
if (diffDays > 7)//year, month and week
{
int age = now.Year - birthday.Year;
if (birthday > now.AddYears(-age))
age--;
if (age > 0)
{
return age + (age > 1 ? " years" : " year");
}
else
{// month and week
DateTime d = birthday;
int diffMonth = 1;
while (d.AddMonths(diffMonth) <= now)
{
diffMonth++;
}
age = diffMonth-1;
if (age == 1 && d.Day > now.Day)
age--;
if (age > 0)
{
return age + (age > 1 ? " months" : " month");
}
else
{
age = diffDays / 7;
return age + (age > 1 ? " weeks" : " week");
}
}
}
else if (diffDays > 0)
{
int age = diffDays;
return age + (age > 1 ? " days" : " day");
}
else
{
int age = diffDays;
return "just born";
}
}
эта реализация прошла ниже тестов.
[TestMethod]
public void TestAge()
{
string age = HowOld(new DateTime(2011, 1, 1), new DateTime(2012, 11, 30));
Assert.AreEqual("1 year", age);
age = HowOld(new DateTime(2011, 11, 30), new DateTime(2012, 11, 30));
Assert.AreEqual("1 year", age);
age = HowOld(new DateTime(2001, 1, 1), new DateTime(2012, 11, 30));
Assert.AreEqual("11 years", age);
age = HowOld(new DateTime(2012, 1, 1), new DateTime(2012, 11, 30));
Assert.AreEqual("10 months", age);
age = HowOld(new DateTime(2011, 12, 1), new DateTime(2012, 11, 30));
Assert.AreEqual("11 months", age);
age = HowOld(new DateTime(2012, 10, 1), new DateTime(2012, 11, 30));
Assert.AreEqual("1 month", age);
age = HowOld(new DateTime(2008, 2, 28), new DateTime(2009, 2, 28));
Assert.AreEqual("1 year", age);
age = HowOld(new DateTime(2008, 3, 28), new DateTime(2009, 2, 28));
Assert.AreEqual("11 months", age);
age = HowOld(new DateTime(2008, 3, 28), new DateTime(2009, 3, 28));
Assert.AreEqual("1 year", age);
age = HowOld(new DateTime(2009, 1, 28), new DateTime(2009, 2, 28));
Assert.AreEqual("1 month", age);
age = HowOld(new DateTime(2009, 2, 1), new DateTime(2009, 3, 1));
Assert.AreEqual("1 month", age);
// NOTE.
// new DateTime(2008, 1, 31).AddMonths(1) == new DateTime(2009, 2, 28);
// new DateTime(2008, 1, 28).AddMonths(1) == new DateTime(2009, 2, 28);
age = HowOld(new DateTime(2009, 1, 31), new DateTime(2009, 2, 28));
Assert.AreEqual("4 weeks", age);
age = HowOld(new DateTime(2009, 2, 1), new DateTime(2009, 2, 28));
Assert.AreEqual("3 weeks", age);
age = HowOld(new DateTime(2009, 2, 1), new DateTime(2009, 3, 1));
Assert.AreEqual("1 month", age);
age = HowOld(new DateTime(2012, 11, 5), new DateTime(2012, 11, 30));
Assert.AreEqual("3 weeks", age);
age = HowOld(new DateTime(2012, 11, 1), new DateTime(2012, 11, 30));
Assert.AreEqual("4 weeks", age);
age = HowOld(new DateTime(2012, 11, 20), new DateTime(2012, 11, 30));
Assert.AreEqual("1 week", age);
age = HowOld(new DateTime(2012, 11, 25), new DateTime(2012, 11, 30));
Assert.AreEqual("5 days", age);
age = HowOld(new DateTime(2012, 11, 29), new DateTime(2012, 11, 30));
Assert.AreEqual("1 day", age);
age = HowOld(new DateTime(2012, 11, 30), new DateTime(2012, 11, 30));
Assert.AreEqual("just born", age);
age = HowOld(new DateTime(2000, 2, 29), new DateTime(2009, 2, 28));
Assert.AreEqual("8 years", age);
age = HowOld(new DateTime(2000, 2, 29), new DateTime(2009, 3, 1));
Assert.AreEqual("9 years", age);
Exception e = null;
try
{
age = HowOld(new DateTime(2012, 12, 1), new DateTime(2012, 11, 30));
}
catch (ArgumentOutOfRangeException ex)
{
e = ex;
}
Assert.IsTrue(e != null);
}
надеюсь, это полезно.
самый простой способ я нашел это. Он работает правильно для США и Западной Европы. Не могу говорить с другими местами, особенно с Китаем. 4 extra сравнивает, самое большее, после первоначального вычисления возраста.
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 ;
}
Я просматривал ответы на этот вопрос и заметил, что никто не упоминал о нормативных/правовых последствиях рождений в високосный день. Например, в Википедии, если вы родились 29 февраля в различных в юрисдикциях, вы не високосный год рождения варьируется:
- в Великобритании и Гонконге: это порядковый день года, поэтому на следующий день, 1 марта-ваш день рождения.
- в Новой Зеландии: это предыдущий день, 28 февраля для целей выдачи водительских прав и 1 марта для других целей.
- Тайвань: это 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;
}
следует отметить, что этот код предполагает:
- западное (европейское) исчисление возраста, и
- календаря, как григорианский календарь, который вставляет один високосный день в конце месяца.
Это один из самых точных ответов, который способен решить день рождения 29 февраля по сравнению с любым годом 28 февраля.
public int GetAge(DateTime birthDate)
{
int age = DateTime.Now.Year - birthDate.Year;
if (birthDate.DayOfYear > DateTime.Now.DayOfYear)
age--;
return age;
}
вот решение.
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);
Я бы сказал, что вопрос не указывает единицу или культуру, в которой измерять возраст, Большинство ответов, похоже, предполагают целочисленное годовое представление. SI-единица измерения времени second
, следовательно, правильный общий ответ должен быть (конечно, при условии нормализованного DateTime
и не обращая никакого внимания на релятивистские эффекты):
var lifeInSeconds = (DateTime.Now.Ticks - then.Ticks)/TickFactor;
по-христиански исчисляя возраст в годах:
var then = ... // Then, in this case the birthday
var now = DateTime.UtcNow;
int age = now.Year - then.Year;
if (now.AddYears(-age) < then) age--;
в финансах существует аналогичная проблема при расчете чего-то часто называемого День Фракция, что примерно составляет несколько лет для данного периода. И вопрос возраста-это действительно вопрос измерения времени.
пример для фактического / фактического (считая все дни "правильно") соглашения:
DateTime start, end = .... // Whatever, assume start is before end
double startYearContribution = 1 - (double) start.DayOfYear / (double) (DateTime.IsLeapYear(start.Year) ? 366 : 365);
double endYearContribution = (double)end.DayOfYear / (double)(DateTime.IsLeapYear(end.Year) ? 366 : 365);
double middleContribution = (double) (end.Year - start.Year - 1);
double DCF = startYearContribution + endYearContribution + middleContribution;
еще один довольно распространенный способ измерение времени обычно происходит путем "сериализации" (чувак, который назвал эту дату, должно быть, серьезно споткнулся):
DateTime start, end = .... // Whatever, assume start is before end
int days = (end - start).Days;
интересно, как долго мы должны идти, прежде чем релятивистский возраст в секундах станет более полезным, чем грубое приближение циклов земля-вокруг-Солнца в течение жизни до сих пор :) или другими словами, когда период должен быть задан местоположение или функция, представляющая движение для себя, чтобы быть действительным :)
Как насчет такого решения?
static string CalcAge(DateTime birthDay)
{
DateTime currentDate = DateTime.Now;
int approximateAge = currentDate.Year - birthDay.Year;
int daysToNextBirthDay = (birthDay.Month * 30 + birthDay.Day) -
(currentDate.Month * 30 + currentDate.Day) ;
if (approximateAge == 0 || approximateAge == 1)
{
int month = Math.Abs(daysToNextBirthDay / 30);
int days = Math.Abs(daysToNextBirthDay % 30);
if (month == 0)
return "Your age is: " + daysToNextBirthDay + " days";
return "Your age is: " + month + " months and " + days + " days"; ;
}
if (daysToNextBirthDay > 0)
return "Your age is: " + --approximateAge + " Years";
return "Your age is: " + approximateAge + " Years"; ;
}
у меня есть индивидуальный метод расчета возраста, а также бонусное сообщение проверки на всякий случай:
public void GetAge(DateTime dob, DateTime now, out int years, out int months, out int days)
{
years = 0;
months = 0;
days = 0;
DateTime tmpdob = new DateTime(dob.Year, dob.Month, 1);
DateTime tmpnow = new DateTime(now.Year, now.Month, 1);
while (tmpdob.AddYears(years).AddMonths(months) < tmpnow)
{
months++;
if (months > 12)
{
years++;
months = months - 12;
}
}
if (now.Day >= dob.Day)
days = days + now.Day - dob.Day;
else
{
months--;
if (months < 0)
{
years--;
months = months + 12;
}
days += DateTime.DaysInMonth(now.AddMonths(-1).Year, now.AddMonths(-1).Month) + now.Day - dob.Day;
}
if (DateTime.IsLeapYear(dob.Year) && dob.Month == 2 && dob.Day == 29 && now >= new DateTime(now.Year, 3, 1))
days++;
}
private string ValidateDate(DateTime dob) //This method will validate the date
{
int Years = 0; int Months = 0; int Days = 0;
GetAge(dob, DateTime.Now, out Years, out Months, out Days);
if (Years < 18)
message = Years + " is too young. Please try again on your 18th birthday.";
else if (Years >= 65)
message = Years + " is too old. Date of Birth must not be 65 or older.";
else
return null; //Denotes validation passed
}
вызов метода здесь и передайте значение datetime (MM/dd/yyyy, если сервер установлен в локаль США). Его ничем заменить MessageBox или любой контейнер на экран:
DateTime dob = DateTime.Parse("03/10/1982");
string message = ValidateDate(dob);
lbldatemessage.Visible = !StringIsNullOrWhitespace(message);
lbldatemessage.Text = message ?? ""; //Ternary if message is null then default to empty string
помните, что вы можете форматировать сообщение так, как вам нравится.
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;
}
я использовал решение ScArcher2 для точного расчета года возраста людей, но мне нужно было взять его дальше и рассчитать их месяцы и дни вместе с годами.
public static Dictionary<string,int> CurrentAgeInYearsMonthsDays(DateTime? ndtBirthDate, DateTime? ndtReferralDate)
{
//----------------------------------------------------------------------
// Can't determine age if we don't have a dates.
//----------------------------------------------------------------------
if (ndtBirthDate == null) return null;
if (ndtReferralDate == null) return null;
DateTime dtBirthDate = Convert.ToDateTime(ndtBirthDate);
DateTime dtReferralDate = Convert.ToDateTime(ndtReferralDate);
//----------------------------------------------------------------------
// Create our Variables
//----------------------------------------------------------------------
Dictionary<string, int> dYMD = new Dictionary<string,int>();
int iNowDate, iBirthDate, iYears, iMonths, iDays;
string sDif = "";
//----------------------------------------------------------------------
// Store off current date/time and DOB into local variables
//----------------------------------------------------------------------
iNowDate = int.Parse(dtReferralDate.ToString("yyyyMMdd"));
iBirthDate = int.Parse(dtBirthDate.ToString("yyyyMMdd"));
//----------------------------------------------------------------------
// Calculate Years
//----------------------------------------------------------------------
sDif = (iNowDate - iBirthDate).ToString();
iYears = int.Parse(sDif.Substring(0, sDif.Length - 4));
//----------------------------------------------------------------------
// Store Years in Return Value
//----------------------------------------------------------------------
dYMD.Add("Years", iYears);
//----------------------------------------------------------------------
// Calculate Months
//----------------------------------------------------------------------
if (dtBirthDate.Month > dtReferralDate.Month)
iMonths = 12 - dtBirthDate.Month + dtReferralDate.Month - 1;
else
iMonths = dtBirthDate.Month - dtReferralDate.Month;
//----------------------------------------------------------------------
// Store Months in Return Value
//----------------------------------------------------------------------
dYMD.Add("Months", iMonths);
//----------------------------------------------------------------------
// Calculate Remaining Days
//----------------------------------------------------------------------
if (dtBirthDate.Day > dtReferralDate.Day)
//Logic: Figure out the days in month previous to the current month, or the admitted month.
// Subtract the birthday from the total days which will give us how many days the person has lived since their birthdate day the previous month.
// then take the referral date and simply add the number of days the person has lived this month.
//If referral date is january, we need to go back to the following year's December to get the days in that month.
if (dtReferralDate.Month == 1)
iDays = DateTime.DaysInMonth(dtReferralDate.Year - 1, 12) - dtBirthDate.Day + dtReferralDate.Day;
else
iDays = DateTime.DaysInMonth(dtReferralDate.Year, dtReferralDate.Month - 1) - dtBirthDate.Day + dtReferralDate.Day;
else
iDays = dtReferralDate.Day - dtBirthDate.Day;
//----------------------------------------------------------------------
// Store Days in Return Value
//----------------------------------------------------------------------
dYMD.Add("Days", iDays);
return dYMD;
}
версия SQL:
declare @dd smalldatetime = '1980-04-01'
declare @age int = YEAR(GETDATE())-YEAR(@dd)
if (@dd> DATEADD(YYYY, -@age, GETDATE())) set @age = @age -1
print @age
Я внес одно небольшое изменение в Марк Соенные это ответ: я переписал третью строку, чтобы выражение можно было разобрать немного легче.
public int AgeInYears(DateTime bday)
{
DateTime now = DateTime.Today;
int age = now.Year - bday.Year;
if (bday.AddYears(age) > now)
age--;
return age;
}
Я также превратил его в функцию для ясности.