# calcular - validar idade c#

## Como calculo a idade de alguém em c#? (20)

A abordagem a seguir (extraída da biblioteca de período de tempo para a classe .NET DateDiff ) considera o calendário das informações da cultura:

``````// ----------------------------------------------------------------------
private static int YearDiff( DateTime date1, DateTime date2 )
{
return YearDiff( date1, date2, DateTimeFormatInfo.CurrentInfo.Calendar );
} // YearDiff

// ----------------------------------------------------------------------
private static int YearDiff( DateTime date1, DateTime date2, Calendar calendar )
{
if ( date1.Equals( date2 ) )
{
return 0;
}

int year1 = calendar.GetYear( date1 );
int month1 = calendar.GetMonth( date1 );
int year2 = calendar.GetYear( date2 );
int month2 = calendar.GetMonth( date2 );

// find the the day to compare
int compareDay = date2.Day;
int compareDaysPerMonth = calendar.GetDaysInMonth( year1, month1 );
if ( compareDay > compareDaysPerMonth )
{
compareDay = compareDaysPerMonth;
}

// build the compare date
DateTime compareDate = new DateTime( year1, month2, compareDay,
date2.Hour, date2.Minute, date2.Second, date2.Millisecond );
if ( date2 > date1 )
{
if ( compareDate < date1 )
{
}
}
else
{
if ( compareDate > date1 )
{
}
}
return year2 - calendar.GetYear( compareDate );
} // YearDiff``````

Uso:

``````// ----------------------------------------------------------------------
public void CalculateAgeSamples()
{
PrintAge( new DateTime( 2000, 02, 29 ), new DateTime( 2009, 02, 28 ) );
// > Birthdate=29.02.2000, Age at 28.02.2009 is 8 years
PrintAge( new DateTime( 2000, 02, 29 ), new DateTime( 2012, 02, 28 ) );
// > Birthdate=29.02.2000, Age at 28.02.2012 is 11 years
} // CalculateAgeSamples

// ----------------------------------------------------------------------
public void PrintAge( DateTime birthDate, DateTime moment )
{
Console.WriteLine( "Birthdate={0:d}, Age at {1:d} is {2} years", birthDate, moment, YearDiff( birthDate, moment ) );
} // PrintAge``````

Dado um `DateTime` representando o aniversário de uma pessoa, como calculo sua idade em anos?

A maneira mais simples que eu já encontrei é essa. Funciona corretamente para os locais dos EUA e da Europa Ocidental. Não posso falar com outros locais, especialmente lugares como a China. 4 compara mais, no máximo, após o cálculo inicial da idade.

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

Eu estava analisando as respostas para isso e percebi que ninguém fez referência às implicações regulatórias / legais dos nascimentos em dias bissextos. Por exemplo, por Wikipedia , se você nasceu em 29 de fevereiro em várias jurisdições, seu aniversário sem ano bissexto varia:

• No Reino Unido e Hong Kong: é o dia ordinal do ano, então no dia seguinte, 1º de março é seu aniversário.
• Na Nova Zelândia: é o dia anterior, 28 de fevereiro para fins de licença de motorista e 1 de março para outros fins.
• Taiwan: é 28 de fevereiro.

E, tanto quanto eu posso dizer, nos EUA, os estatutos ficam em silêncio sobre o assunto, deixando o direito comum e a forma como vários órgãos reguladores definem as coisas em seus regulamentos.

Para esse fim, uma melhoria:

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

case LeapDayRule.LastDayOfMonth:
cutoff = new DateTime(reference.Year, birth.Month, 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;
}``````

Note-se que este código assume:

• Um acerto de contas ocidental (europeu) da idade e
• Um calendário, como o calendário gregoriano que insere um único dia bissexto no final de um mês.

Essa pergunta clássica merece uma solução Noda Time .

``````static int GetAge(LocalDate dateOfBirth)
{
Instant now = SystemClock.Instance.Now;

// The target time zone is important.
// It should align with the *current physical location* of the person
// you are talking about.  When the whereabouts of that person are unknown,
// then you use the time zone of the person who is *asking* for the age.
// The time zone of birth is irrelevant!

DateTimeZone zone = DateTimeZoneProviders.Tzdb["America/New_York"];

LocalDate today = now.InZone(zone).Date;

Period period = Period.Between(dateOfBirth, today, PeriodUnits.Years);

return (int) period.Years;
}``````

Uso:

``````LocalDate dateOfBirth = new LocalDate(1976, 8, 27);
int age = GetAge(dateOfBirth);``````

Você também pode estar interessado nas seguintes melhorias:

• Passar o relógio como `IClock` , em vez de usar `SystemClock.Instance` , melhoraria a testabilidade.

• O fuso horário alvo provavelmente será alterado, então você também desejará um `DateTimeZone` parâmetro.

Veja também meu post sobre este assunto: Manipulação de aniversários e outros aniversários

Esta é uma das respostas mais precisas que podem resolver o aniversário de 29 de fevereiro, comparada a qualquer ano de 28 de fevereiro.

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

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

return age;
}``````

Eu tenho um método personalizado para calcular a idade, além de uma mensagem de validação de bônus, caso isso ajude:

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

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

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

Chame o método aqui e passe o valor de data e hora (MM / dd / aaaa se o servidor estiver definido como localidade dos EUA). Substitua por qualquer caixa de mensagens ou recipiente para exibir:

``````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``````

Lembre-se de que você pode formatar a mensagem da maneira que desejar.

Que tal esta solução?

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

Versão 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  ``````

2 Os principais problemas a serem resolvidos são:

1. Calcule a idade exata - em anos, meses, dias etc.

2. Calcular a idade geralmente percebida - as pessoas geralmente não se importam com a idade exata, apenas se importam com o aniversário do ano atual.

A solução para 1 é óbvia:

``````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``````

A solução para 2 é a que não é tão precisa na determinação da idade total, mas é percebida como precisa pelas pessoas. As pessoas também costumam usá-lo, quando calculam sua idade "manualmente":

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

Notas 2:

• Esta é a minha solução preferida
• Não podemos usar DateTime.DayOfYear ou TimeSpans, pois eles mudam o número de dias nos anos bissextos
• Coloquei pouco mais linhas para facilitar a leitura

Apenas mais uma observação ... Eu criaria dois métodos estáticos sobrecarregados, um para uso universal e outro para facilidade de uso:

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

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

A resposta simples para isso é aplicar `AddYears` como mostrado abaixo, porque este é o único método nativo para adicionar anos ao dia 29 de fevereiro dos anos bissextos e obter o resultado correto do dia 28 de fevereiro nos anos comuns.

Alguns acham que 1º de março é o aniversário dos pulos, mas nem o .Net nem nenhuma regra oficial apóiam isso, nem a lógica comum explica por que alguns nascidos em fevereiro devem ter 75% de seus aniversários em outro mês.

Além disso, um método Age se presta a ser adicionado como uma extensão ao `DateTime` . Com isso, você pode obter a idade da maneira mais simples possível:

1. Item da lista

``````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)
{
}
else
{
age = 0;
}

return age;
}
}``````

Agora, execute este teste:

``````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++)
{
}
}

}
}``````

O exemplo da data crítica é este:

Data de nascimento: 2000-02-29 Data posterior: 2011-02-28 Idade: 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
}``````

E para a data posterior 28/02/2012:

``````{
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
}``````

Acho que nenhuma das respostas até agora prevê culturas que calculam a idade de maneira diferente. Veja, por exemplo, o cálculo da idade na Ásia Oriental versus o do Ocidente.

Qualquer resposta real precisa incluir a localização. O padrão de estratégia provavelmente estaria em ordem neste exemplo.

Essa é uma maneira estranha de fazer isso, mas se você formatar a data para `yyyymmdd` e subtrair a data de nascimento da data atual, solte os últimos 4 dígitos que você tem a idade :)

Não sei c #, mas acredito que isso funcione em qualquer idioma.

``20080814 - 19800703 = 280111 ``

Solte os últimos 4 dígitos = `28` .

Código C #:

``````int now = int.Parse(DateTime.Now.ToString("yyyyMMdd"));
int dob = int.Parse(dateOfBirth.ToString("yyyyMMdd"));
int age = (now - dob) / 10000;``````

Ou, alternativamente, sem toda a conversão de tipo na forma de um método de extensão. Verificação de erro omitida:

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

Esta é a versão que usamos aqui. Funciona e é bastante simples. É a mesma ideia que a de Jeff, mas acho que é um pouco mais clara, porque separa a lógica de subtrair uma, por isso é um pouco mais fácil de entender.

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

Você pode expandir o operador ternário para torná-lo ainda mais claro, se achar que esse tipo de coisa não é clara.

Obviamente, isso é feito como um método de extensão no `DateTime` , mas claramente você pode pegar aquela linha de código que faz o trabalho e colocá-la em qualquer lugar. Aqui temos outra sobrecarga do método Extension que passa no `DateTime.Now` , apenas para ser completo.

Eu criei uma Função Definida pelo Usuário do SQL Server para calcular a idade de alguém, dada a data de nascimento. Isso é útil quando você precisa dele como parte de uma consulta:

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

Eu uso isso:

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

Mantendo-o simples (e possivelmente estúpido :)).

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

Minha sugestão

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

Parece que o ano está mudando na data certa. (Eu testei até 107 anos de idade)

Outra função, não por mim, mas encontrada na web e refinada um pouco:

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

Apenas duas coisas que me vêm à cabeça: E as pessoas de países que não usam o calendário gregoriano? DateTime.Now está na cultura específica do servidor, eu acho. Não tenho absolutamente nenhum conhecimento sobre como trabalhar com calendários asiáticos e não sei se há uma maneira fácil de converter datas entre calendários, mas, caso você esteja se perguntando sobre os chineses do ano 4660 :-)

Passei algum tempo trabalhando nisso e criei isso para calcular a idade de alguém em anos, meses e dias. Eu testei contra o problema de 29 de fevereiro e os anos bissextos e parece funcionar, eu gostaria de receber algum feedback:

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

{
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.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++;
}

}``````

Uma solução fácil de entender e simples.

``````// 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

No entanto, isso pressupõe que você esteja procurando a idéia ocidental de idade e não esteja usando o cálculo da Ásia Oriental .

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