Сведения о вопросе

Fedya

16:03, 1st July, 2020

Теги

c#   .net   datetime    

Как я могу вычислить чей-то возраст в C#?

Просмотров: 1322   Ответов: 25

Учитывая, что DateTime представляет собой день рождения человека, как я могу рассчитать его возраст в годах?



  Сведения об ответе

SILA

18:03, 1st July, 2020

Простое и понятное решение.

// 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.Date > today.AddYears(-age)) age--;

Однако это предполагает, что вы ищете западную идею возраста и не используете восточноазиатское исчисление .


  Сведения об ответе

P_S_S

18:03, 1st July, 2020

Это странный способ сделать это, но если вы отформатируете дату в 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;
}


  Сведения об ответе

P_S_S

18:03, 1st July, 2020

Я не знаю, как можно принять неправильное решение. Правильный фрагмент C# был написан Майклом СТЭМом

Вот фрагмент теста:

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;
}


  Сведения об ответе

lats

18:03, 1st July, 2020

Я не думаю, что какие-либо из ответов до сих пор дают культуры, которые вычисляют возраст по-разному. См., например, сравнение возраста Восточной Азии с возрастом на Западе.

Любой реальный ответ должен включать локализацию. Вероятно, в этом примере модель Стратегии была бы в порядке вещей.


  Сведения об ответе

screen

18:03, 1st July, 2020

Простой ответ на это-применить AddYears , как показано ниже, потому что это единственный родной метод для добавления лет к 29 февраля. високосных лет и получить правильный результат 28 февраля. для обычных лет.

Некоторые считают, что 1 марта. это день рождения леаплингов, но ни .Net, ни какое-либо официальное правило не поддерживает это, и общая логика не объясняет, почему некоторые родившиеся в феврале должны иметь 75% своих дней рождения в другом месяце.

Кроме того, метод Age может быть добавлен в качестве расширения к DateTime . Таким образом вы можете получить возраст самым простым способом:

  1. Элемент списка

инт возраст = birthDate.Age();

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
}


  Сведения об ответе

screen

18:03, 1st July, 2020

Мое предложение

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

Похоже, что год меняется в нужную дату. (Я тестируюсь до 107 лет)


  Сведения об ответе

COOL

18:03, 1st July, 2020

Еще одна функция, не мной, но найденная в интернете и немного доработанная:

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 года :-)


  Сведения об ответе

DO__IT

18:03, 1st July, 2020

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 -это то, которое не так точно определяет общий возраст, но воспринимается людьми как точное. Люди также обычно используют его, когда они вычисляют свой возраст "manually":

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 или TimeSpans, так как они смещают количество дней в високосные годы
  • Я поставил там немного больше строк для удобства чтения

Только еще одна записка ... Я бы создал для него 2 статических перегруженных метода, один для универсального использования, второй для удобства использования:

public static int GetAge(DateTime bithDay, DateTime today) 
{ 
  //chosen solution method body
}

public static int GetAge(DateTime birthDay) 
{ 
  return GetAge(birthDay, DateTime.Now);
}


  Сведения об ответе

screen

18:03, 1st July, 2020

Я опаздываю на вечеринку, но вот вам один лайнер:

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


  Сведения об ответе

FAriza

18:03, 1st July, 2020

Это версия, которую мы используем здесь. Это работает, и это довольно просто. Это та же самая идея, что и у Джеффа, но я думаю, что она немного яснее, потому что она отделяет логику для вычитания одного, поэтому ее немного легче понять.

public static int GetAge(this DateTime dateOfBirth, DateTime dateAsAt)
{
    return dateAsAt.Year - dateOfBirth.Year - (dateOfBirth.DayOfYear < dateAsAt.DayOfYear ? 0 : 1);
}

Вы можете расширить тернарный оператор, чтобы сделать его еще более ясным, если вы думаете, что такого рода вещи неясны.

Очевидно, что это делается в качестве метода расширения на DateTime, но очевидно, что вы можете захватить ту одну строку кода, которая выполняет эту работу, и поместить ее в любом месте. Здесь мы имеем еще одну перегрузку метода расширения, который проходит в DateTime.Now, просто для полноты картины.


  Сведения об ответе

PHPH

18:03, 1st July, 2020

Самый лучший способ, который я знаю, потому что високосные годы и все остальное-это:

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

Надеюсь, это поможет.


  Сведения об ответе

park

18:03, 1st July, 2020

Я использую это:

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;
    }
}


  Сведения об ответе

piter

18:03, 1st July, 2020

Это дает "more detail" на этот вопрос. Может быть, это то, что вы ищете

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);


  Сведения об ответе

appple

18:03, 1st July, 2020

Я создал пользовательскую функцию 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;
    }
};


  Сведения об ответе

DO__IT

18:03, 1st July, 2020

Я потратил некоторое время, работая над этим, и придумал это, чтобы вычислить чей-то возраст в годах, месяцах и днях. Я протестировал против проблемы 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++;
    }

}


  Сведения об ответе

SILA

18:03, 1st July, 2020

Вот еще один ответ:

public static int AgeInYears(DateTime birthday, DateTime today)
{
    return ((today.Year - birthday.Year) * 372 + (today.Month - birthday.Month) * 31 + (today.Day - birthday.Day)) / 372;
}

Это было тщательно проверено на практике. Это действительно выглядит немного "magic". Число 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 , если она еще не достигнута.

а) если 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

Б) если 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

д) Если Mn=Mb и Dn=Db, то мы имеем 31*(Mn - Mb) + Dn-Db = 0

и потому (31*(Mn - Mb) + (Dn - Db)) / 372 = 0


  Сведения об ответе

#hash

18:03, 1st July, 2020

Нужно ли рассматривать людей, которым меньше 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);
}

Надеюсь, это поможет.


  Сведения об ответе

SEEYOU

18:03, 1st July, 2020

Сохраняя его простым (и, возможно, глупым:)).

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.");


  Сведения об ответе

LIZA

18:03, 1st July, 2020

Самый простой способ, который я когда-либо находил, - это вот это. Он корректно работает для локалей US и Западной Европы. Не могу говорить с другими регионами, особенно в таких местах, как Китай. 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 февраля.

И насколько я могу судить, в 30-х годах статуты умалчивают об этом вопросе, оставляя его на усмотрение общего права и на то, как различные регулирующие органы определяют вещи в своих постановлениях.

С этой целью, улучшение:

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;
}

Следует отметить, что данный код предполагает:

  • Западное (европейское) исчисление возраста, и
  • Календарь, как григорианский календарь, который вставляет один високосный день в конце месяца.


  Сведения об ответе

P_S_S

18:03, 1st July, 2020

TimeSpan diff = DateTime.Now - birthdayDateTime;
string age = String.Format("{0:%y} years, {0:%M} months, {0:%d}, days old", diff);

Я не знаю, как именно вы хотели бы его вернуть, поэтому я просто сделал читаемую строку.


  Сведения об ответе

VCe znayu

18:03, 1st July, 2020

Вот вам и решение.

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);


  Сведения об ответе

SKY

18:03, 1st July, 2020

Это не прямой ответ, а скорее философское рассуждение о рассматриваемой проблеме с квазинаучной точки зрения.

Я бы сказал, что вопрос не указывает ни единицу измерения, ни культуру, в которой измеряется возраст, Большинство ответов, по-видимому, предполагают целочисленное годовое представление. 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--;

В финансах существует аналогичная проблема при расчете чего-то , часто называемого дробью счета дней, которая примерно равна числу лет за данный период. А вопрос возраста-это действительно вопрос измерения времени.

Пример для конвенции actual/actual (подсчет всех дней "correctly") :

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;

Еще один довольно распространенный способ измерения времени в целом-это "serializing" (чувак, который назвал эту дату условностью, должно быть, серьезно споткнулся):

DateTime start, end = .... // Whatever, assume start is before end
int days = (end - start).Days;

Я задаюсь вопросом, как долго мы должны идти, прежде чем релятивистский возраст в секундах станет более полезным, чем грубое приближение earth-around-sun-cycles в течение жизни до сих пор :) или другими словами, когда период должен быть задан местоположением или функцией, представляющей движение, чтобы быть действительным :)


  Сведения об ответе

pumpa

18:03, 1st July, 2020

Это один из самых точных ответов, который способен решить день рождения 29 февраля по сравнению с любым годом 28 февраля.

public int GetAge(DateTime birthDate)
{
    int age = DateTime.Now.Year - birthDate.Year;

    if (birthDate.DayOfYear > DateTime.Now.DayOfYear)
        age--;

    return age;
}


  Сведения об ответе

PAGE

18:03, 1st July, 2020

У меня есть индивидуальный метод расчета возраста, а также бонусное сообщение проверки на всякий случай, если это поможет:

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, если сервер установлен в USA locale). Замените это на что угодно 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

Помните, что вы можете форматировать сообщение так, как вам нравится.


  Сведения об ответе

prince

18:03, 1st July, 2020

Как насчет этого решения?

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"; ;
}


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться