In C #, come posso calcolare l'età di qualcuno in base a un compleanno di tipo DateTime?


1868

Dato che DateTimerappresenta il compleanno di una persona, come posso calcolare la sua età in anni?


147
ciò che tutte le risposte finora mancate è che dipende da dove è nata la persona e dove si trova adesso.
Yaur,

40
@Yaur: basta convertire l'ora di ora + nascita in GMT / UTC, l'età è solo un valore relativo, quindi i fusi orari sono irrilevanti. Per determinare il fuso orario corrente dell'utente, è possibile utilizzare GeoLocating.
Stefan Steiger,

Perché non considerare [Julian Date] [1]? [1]: stackoverflow.com/questions/7103064/…
Muhammad Hewedy

5
Se prendiamo in considerazione il suggerimento di @Yaur di calcoli del fuso orario incrociato, l'ora legale dovrebbe influenzare il calcolo in qualche modo?
DDM

6
Sottovalutato perché questa è chiaramente una domanda a casa e non è stato fornito alcun tentativo esistente.
Marie,

Risposte:


2122

Una soluzione facile da capire e semplice.

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

Tuttavia, questo presuppone che tu stia cercando l' idea occidentale dell'età e non usi la resa dei conti dell'Asia orientale .


252
Volevo solo commentare le prestazioni di DateTime.Now. Se non hai bisogno di un valore preciso del fuso orario, usa DateTime.UtcNow è molto più veloce.
JAG

104
Dato che stiamo parlando di compleanni, puoi semplicemente usare DateTime. Oggi dato che la parte del tempo non ha rilevanza.
Tristan Warner-Smith,

78
Questa risposta non funziona con tutti i locali e tutte le età. Diversi paesi hanno saltato le date dopo la nascita degli attuali viventi, tra cui Russia (1918), Grecia (1924) e Turchia (1926).
Lars D,

30
In realtà, non è ancora del tutto corretto. Questo codice presume che "bday" sia la porzione di data di un DateTime. È un caso limite (immagino che la maggior parte delle persone passerà solo date e non date-orari), ma se passi un compleanno come data e ora in cui l'ora è maggiore di 00:00:00, allora ' Incontrerò il bug che Danvil ha sottolineato. L'impostazione di bday = bday.Date risolve questo problema.
Øyvind

119
L'ultima riga mi ha fatto pensare troppo. Invece che ne dici di: if (bday.AddYears (age)> now) age--; Questa sembra essere un'espressione più intuitiva.
cdiggins,

1015

Questo è uno strano modo di farlo, ma se si formatta la data a yyyymmdd e sottragga la data di nascita dalla data corrente, allora abbandoni le ultime 4 cifre hai l'età :)

Non conosco C #, ma credo che funzionerà in qualsiasi lingua.

20080814 - 19800703 = 280111 

Rilascia le ultime 4 cifre = 28 .

Codice C #:

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

O in alternativa senza tutta la conversione del tipo sotto forma di un metodo di estensione. Errore nel controllo omesso:

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

5
In realtà questo è ottimo per l'utilizzo su MS-SQL con campi datetime (giorni totali dal 01-011900)
Patrik

5
@numerek Inserisci le modifiche suggerite come risposta. Per quello che vale, l'anno in corso 10000 non è affatto vicino a un trabocco intero, di due ordini di grandezza. 20.150.000 vs 2.147.483.648
GalacticCowboy

7
@LongChalk 20180101 - 20171231 = 8870. Rilascia le ultime 4 cifre e hai (un implicito) 0per l'età. Come hai fatto 1?
Rufus L

4
So che questa è una vecchia risposta, ma non ne ricaverei un metodo di estensione, non è il posto giusto per definire tali logiche.
Lucca Ferri,

1
Che tipo di stregoneria è questa?
Muleskinner

391

Ecco uno snippet di prova:

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
                CalculateAgeCorrect2(bDay, now)));  // outputs 8

Ecco i metodi:

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 int CalculateAgeCorrect2(DateTime birthDate, DateTime now)
{
    int age = now.Year - birthDate.Year;

    // For leap years we need this
    if (birthDate > now.AddYears(-age)) 
        age--;
    // Don't use:
    // if (birthDate.AddYears(age) > now) 
    //     age--;

    return age;
}

33
Mentre questo codice funziona, afferma che una persona nata in un giorno bisestile raggiunge il prossimo anno di età il 1 ° marzo negli anni non bisestili, piuttosto che il 28 febbraio. In realtà, entrambe le opzioni potrebbero essere corrette . Wikipedia ha qualcosa da dire al riguardo . Quindi, mentre il tuo codice non è "sbagliato", non è nemmeno la soluzione accettata.
Matt Johnson-Pint,

18
@MattJohnson Penso che sia effettivamente corretto. Se il mio compleanno era il 29 febbraio, quindi il 28 febbraio il mio compleanno non è passato e dovrei avere ancora la stessa età del 27 febbraio. Il 1 ° marzo, tuttavia, abbiamo passato il mio compleanno e dovrei essere l'età successiva. Negli Stati Uniti, un'azienda che vende alcolici avrà un cartello che dice "Se sei nato dopo questo giorno a AAAA, non puoi acquistare alcolici" (dove AAAA cambia ogni anno). Ciò significa che qualcuno nato il 29 febbraio non può comprare alcolici il 28 febbraio dell'anno in cui compiono 21 anni (la maggior parte dei posti) e sostiene l'idea di non avere più di un anno fino al 1 ° marzo.
jfren484

4
@ jfren484 - leggi l'articolo di Wikipedia. Varia notevolmente tra le giurisdizioni.
Matt Johnson-Pint,

9
@ jfren484 La tua affermazione non ha assolutamente nulla a che fare con la filosofia; ma tutto a che fare con il tuo sentimento personale . Quando una persona nata il 29 febbraio, "l'età" è in gran parte irrilevante, a meno che l'età non costituisca un "limite legale dell'età" (ad es. Può comprare alcolici, votare, ottenere una pensione, arruolarsi nell'esercito, ottenere la patente di guida). Considera l'età per bere negli Stati Uniti (21 anni): per la maggior parte delle persone sono 7670 giorni. Sono 7671 giorni se nati prima del 29 febbraio dell'anno bisestile o dal 1 marzo prima dell'anno bisestile. Se nato il 29 febbraio: 28 febbraio è 7670 giorni e 1 marzo è 7671 giorni. La scelta è arbitraria , può andare in entrambi i modi.
Disilluso il

4
@CraigYoung Non capisci cosa intendevo filosoficamente. Ho usato quel termine come un contrasto legalmente. Se uno sta scrivendo una domanda che deve conoscere l'età legale di una persona, tutto ciò che deve sapere è come le giurisdizioni legali in cui viene utilizzata la sua domanda / per trattare le persone nate il 29 febbraio. Se, tuttavia, siamo parlando di come dovrebbe essere trattato, quindi per definizione, filosofia. E sì, l'opinione che ho dato è la mia opinione, ma come ho detto, penso che sarebbe più facile discutere per il 1 marzo di quanto non lo sarebbe per il 28 febbraio.
jfren484

110

La semplice risposta a questa domanda è di applicare AddYearscome mostrato di seguito perché questo è l'unico metodo nativo per aggiungere anni al 29 febbraio degli anni bisestili e ottenere il risultato corretto del 28 febbraio per gli anni comuni.

Alcuni ritengono che il 1 ° marzo sia il compleanno dei salti, ma né .Net né alcuna regola ufficiale lo sostengono, né la logica comune spiega perché alcuni nati a febbraio dovrebbero avere il 75% dei loro compleanni in un altro mese.

Inoltre, un metodo Age si presta ad essere aggiunto come estensione a DateTime. Con questo puoi ottenere l'età nel modo più semplice possibile:

  1. Voce di elenco

int age = 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;
    }
}

Ora esegui questo test:

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

L'esempio della data critica è questo:

Data di nascita: 2000-02-29 Data successiva: 2011-02-28 Età: 11

Produzione:

{
    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 per la data successiva 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
}

4
Un commento riguardante il compleanno del 29 febbraio il 1 ° marzo, tecnicamente, averlo il 28 è troppo presto (1 giorno in anticipo). Il primo è un giorno troppo tardi. Ma poiché il compleanno è tra, usare il 1 ° per calcolare l'età in anni non bisestili ha più senso per me, dal momento che quella persona è davvero così vecchia il 1 ° marzo (e il 2 ° e il 3 °) ogni anno, ma non il 28 febbraio.
CyberClaw

1
Da un punto di vista della progettazione software, scrivere questo come metodo di estensione non ha molto senso per me. date.Age(other)?
Marsze,

90

Il mio consiglio

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

Sembra che l'anno cambi nella data giusta. (Ho individuato un test fino a 107 anni.)


26
Non credo che Harry Patch avrebbe apprezzato la tua metodologia di test in loco: latimes.com/news/obituaries/…
MusiGenesis

3
Google dicedays in a year = 365.242199
mpen

12
La durata media di un anno nel calendario gregoriano è di 365.2425 giorni.
dan04,

4
Direi che questa è una delle soluzioni più semplici ed è abbastanza buona . Chi se ne frega se sono mezza giornata prima del mio X compleanno e il programma dice che ho X anni. Il programma è più o meno giusto, anche se non matematicamente. Mi piace molto questa soluzione.
Peter Perháč,

13
^^ Perché a volte è importante. Nei miei test questo non riesce nel giorno del compleanno delle persone, le riporta più giovani di loro.
ChadT

76

Un'altra funzione, non da parte mia, ma trovata sul web e perfezionata un po ':

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

Solo due cose che mi vengono in mente: che dire delle persone provenienti da paesi che non usano il calendario gregoriano? DateTime.Now è nella cultura specifica del server penso. Ho una conoscenza assolutamente nulla su come lavorare effettivamente con i calendari asiatici e non so se c'è un modo semplice per convertire le date tra i calendari, ma nel caso ti stia chiedendo di quei ragazzi cinesi dell'anno 4660 :-)


Questo sembra gestire al meglio diverse regioni (formati di data).
webdad3,

53

2 I problemi principali da risolvere sono:

1. Calcola l'età esatta - in anni, mesi, giorni, ecc.

2. Calcola l'età generalmente percepita : alle persone di solito non importa quanti anni hanno esattamente, si preoccupano solo del loro compleanno nell'anno in corso.


La soluzione per 1 è ovvia:

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

La soluzione per 2 è quella che non è così precisa nel determinare l'età totale, ma è percepita come precisa dalle persone. Le persone di solito lo usano anche, quando calcolano la loro età "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
}

Note per 2 .:

  • Questa è la mia soluzione preferita
  • Non possiamo usare DateTime.DayOfYear o TimeSpans, poiché spostano il numero di giorni negli anni bisestili
  • Ho messo lì poche righe in più per la leggibilità

Solo un'altra nota ... Vorrei creare 2 metodi statici sovraccaricati, uno per uso universale, secondo per facilità d'uso:

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

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

50

Ecco un one-liner:

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

23
Questo è rotto. Reso testabile: int statico pubblico CalculateAge (DateTime dateOfBirth, DateTime dateToCalculateAge) {return new DateTime (dateToCalculateAge.Subtract (dateOfBirth) .Ticks) .Year - 1; } ... Ha 14 anni quando inserisco 1990-06-01 e calcola l'età del giorno PRIMA del suo 14 ° compleanno (1990-05-31).
Kjensen,

43

Questa è la versione che usiamo qui. Funziona ed è abbastanza semplice. È la stessa idea di quella di Jeff ma penso che sia un po 'più chiara perché separa la logica per sottrarne una, quindi è un po' più facile da capire.

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

Potresti espandere l'operatore ternario per renderlo ancora più chiaro, se pensi che questo genere di cose non sia chiaro.

Ovviamente questo viene fatto come metodo di estensione DateTime, ma chiaramente puoi prendere quella riga di codice che fa il lavoro e metterlo ovunque. Qui abbiamo un altro sovraccarico del metodo Extension che passa DateTime.Now, solo per completezza.


6
Penso che questo possa spegnersi di un giorno quando esattamente uno di DateOfBirth o DateAsAt cade in un anno bisestile. Considera l'età di una persona nata il 1 ° marzo 2003 il 29 febbraio 2004. Per rettificare questo, devi fare un confronto lessicografico di coppie (Month, DayOfMonth) e usarlo per il condizionale.
Doug McClean,

1
inoltre non mostrerà l'età giusta per il tuo compleanno.
dotjoe,

43

Il modo migliore che conosco a causa degli anni bisestili e tutto è:

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

34

Io lo uso questo:

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

32

Questo dà "maggiori dettagli" a questa domanda. Forse questo è quello che stai cercando

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

1
Questo non funziona sempre. L'aggiunta di un intervallo a DateTime.MinValue potrebbe funzionare su boe questo non tiene conto degli anni bisestili ecc. Se si aggiungono anni, mesi e giorni a Age utilizzando la funzione AddYears (), AddMonths e AddDays () non restituirà sempre Datetime Ora.
Athanasios Kataras il

3
lo stesso periodo di tempo tiene automaticamente conto degli anni bisestili tra 2 date, quindi non sono sicuro di cosa ti stai occupando. Ho chiesto sui forum di Microsoft e Microsoft ha confermato che tiene conto degli anni bisestili tra 2 date.
Jacqueline Loriault,

2
Considera i seguenti DUE senari. 1st DateTime.Now è l'1 / 1/2001 e un bambino è nato l'1 / 1/2000. Il 2000 è un anno bisestile e il risultato sarà 1 anno, 0 mesi e 1 giorni. Nel secondo senarion DateTime.Now è il 1/1/2002 e il bambino nasce l'1 / 1/2001. In questo caso il risultato sarà di 1 anno, 0 mesi e 0 giorni. Ciò accadrà perché stai aggiungendo il periodo di tempo in un anno non bisestile. Se DateTime.MinValue fosse un anno bisestile, i risultati sarebbero 1 anno al primo e 0 anni 11 mesi e 30 giorni. (Provalo nel tuo codice).
Athanasios Kataras,

1
Upvote! Ho trovato una soluzione praticamente identica (ho usato DateTime.MinValue.AddTicks (span.Ticks) invece di +, ma il risultato è lo stesso e il tuo ha pochi caratteri in meno di codice).
Makotosan,

4
Hai ragione, non lo è. Ma se fosse questo sarebbe il risultato. Perchè importa? Non In entrambi i casi, saltare o no, ci sono esempi in cui questo non funziona. Era quello che volevo mostrare. Il DIFF è corretto. L'intervallo tiene conto degli anni bisestili. Ma l'aggiunta a una data di base non lo è. Prova gli esempi nel codice e vedrai che ho ragione.
Athanasios Kataras,

28

Ho creato una funzione definita dall'utente di SQL Server per calcolare l'età di qualcuno, data la sua data di nascita. Ciò è utile quando è necessario come parte di una query:

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

28

Ecco un'altra risposta:

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

Questo è stato ampiamente testato dall'unità. Sembra un po '"magico". Il numero 372 è il numero di giorni che ci sarebbero in un anno se ogni mese avesse 31 giorni.

La spiegazione del perché funziona ( sollevato da qui ) è:

Let's set 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

Sappiamo che ciò di cui abbiamo bisogno è Yn-Ybse la data è già stata raggiunta, in Yn-Yb-1caso contrario.

a) Se Mn<Mblo abbiamo-341 <= 31*(Mn-Mb) <= -31 and -30 <= Dn-Db <= 30

-371 <= 31*(Mn - Mb) + (Dn - Db) <= -1

Con divisione intera

(31*(Mn - Mb) + (Dn - Db)) / 372 = -1

b) Se Mn=Mbe Dn<Db, abbiamo31*(Mn - Mb) = 0 and -30 <= Dn-Db <= -1

Con divisione intera, di nuovo

(31*(Mn - Mb) + (Dn - Db)) / 372 = -1

c) Se Mn>Mblo abbiamo31 <= 31*(Mn-Mb) <= 341 and -30 <= Dn-Db <= 30

1 <= 31*(Mn - Mb) + (Dn - Db) <= 371

Con divisione intera

(31*(Mn - Mb) + (Dn - Db)) / 372 = 0

d) Se Mn=Mbe Dn>Db, abbiamo 31*(Mn - Mb) = 0 and 1 <= Dn-Db <= 30

Con divisione intera, di nuovo

(31*(Mn - Mb) + (Dn - Db)) / 372 = 0

e) Se Mn=Mbe Dn=Db, abbiamo31*(Mn - Mb) + Dn-Db = 0

e quindi (31*(Mn - Mb) + (Dn - Db)) / 372 = 0


3
Mi sono imbattuto in questa discussione lunga e fastidiosa, e la tua soluzione è un approccio davvero carino e piccolo. Grazie per averlo reso semplice
nabuchodonossor

25

Ho passato un po 'di tempo a lavorare su questo e ho pensato a questo per calcolare l'età di qualcuno in anni, mesi e giorni. Ho testato contro il problema del 29 febbraio e gli anni bisestili e sembra funzionare, apprezzerei qualsiasi 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);

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

}

21

Dobbiamo considerare le persone di età inferiore a 1 anno? come cultura cinese, descriviamo l'età dei bambini piccoli come 2 mesi o 4 settimane.

Di seguito è la mia implementazione, non è semplice come quello che immaginavo, soprattutto per gestire la data come il 28/02.

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

Questa implementazione è passata sotto i casi di test.

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

Spero sia utile.


20

Mantenerlo semplice (e possibilmente stupido :)).

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 è stata la mia prima scelta, ma ha scoperto che non offre una proprietà TotalYears. Potresti provare (ts.TotalDays / 365) - ma non tiene conto degli anni bisestili ecc.
Lazlow,

19

Il modo più semplice che abbia mai trovato è questo. Funziona correttamente per le località degli Stati Uniti e dell'Europa occidentale. Non posso parlare con altri locali, in particolare posti come la Cina. 4 ulteriori confronti, al massimo, dopo il calcolo iniziale dell'età.

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

Stavo esaminando le risposte a questo e ho notato che nessuno ha fatto riferimento alle implicazioni normative / legali delle nascite del giorno bisestile. Ad esempio, per Wikipedia , se sei nato il 29 febbraio in varie giurisdizioni, il tuo compleanno non bisestile varia:

  • Nel Regno Unito e a Hong Kong: è il giorno ordinale dell'anno, quindi il giorno successivo, il 1 ° marzo è il tuo compleanno.
  • In Nuova Zelanda: è il giorno precedente, il 28 febbraio ai fini della patente di guida e il 1 ° marzo per altri scopi.
  • Taiwan: è il 28 febbraio.

E per quanto posso dire, negli Stati Uniti, gli statuti tacciono sulla questione, lasciandola alla legge comune e al modo in cui i vari organi regolatori definiscono le cose nei loro regolamenti.

A tal fine, un miglioramento:

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

Va notato che questo codice presuppone:

  • Una resa dei conti occidentale (europea) dell'età e
  • Un calendario, come il calendario gregoriano che inserisce un solo giorno bisestile alla fine di un mese.

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

Non sono sicuro di come esattamente ti piacerebbe che ti venisse restituito, quindi ho appena creato una stringa leggibile.


18

Questa non è una risposta diretta, ma più un ragionamento filosofico sul problema attuale da un punto di vista quasi scientifico.

Direi che la domanda non specifica l'unità o la cultura in cui misurare l'età, la maggior parte delle risposte sembra assumere una rappresentazione annuale intera. L'unità SI per il tempo è second, ergo, la risposta generica corretta dovrebbe essere (ovviamente assumendo normalizzata DateTimee senza tenere in alcun modo conto degli effetti relativistici):

var lifeInSeconds = (DateTime.Now.Ticks - then.Ticks)/TickFactor;

Nel modo cristiano di calcolare l'età in anni:

var then = ... // Then, in this case the birthday
var now = DateTime.UtcNow;
int age = now.Year - then.Year;
if (now.AddYears(-age) < then) age--;

Nella finanza c'è un problema simile quando si calcola qualcosa spesso definito come la frazione di conteggio dei giorni , che è approssimativamente un numero di anni per un determinato periodo. E il problema dell'età è davvero un problema di misurazione del tempo.

Esempio per la convenzione effettiva / effettiva (contando tutti i giorni "correttamente"):

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;

Un altro modo abbastanza comune per misurare il tempo è in genere "serializzando" (il tizio che ha chiamato questa convenzione della data deve aver seriamente inciampato):

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

Mi chiedo quanto tempo dobbiamo passare prima che un'età relativistica in pochi secondi diventi più utile della approssimazione approssimativa dei cicli terra-intorno-sole durante la vita fino ad ora :) O in altre parole, quando a un periodo deve essere assegnato un luogo o una funzione che rappresenta il movimento per se stessa per essere valida :)


Che cos'è TickFactor ?
Protiguo

@Protiguous Ticks al secondo, utilizzato per normalizzare le tick in secondi.
Flindeberg

17

Ecco una soluzione

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

Con lo string concat, questo sarebbe possibile: 47 anni 11 Mo 7 giorni
JoshYates1980

16

Questa è una delle risposte più accurate che è in grado di risolvere il compleanno del 29 febbraio rispetto a qualsiasi anno del 28 febbraio.

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

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

    return age;
}




È oggi! (Il prossimo è tra quattro anni.)
Peter Mortensen,

15

Ho un metodo personalizzato per calcolare l'età, oltre a un messaggio di convalida del bonus nel caso in cui aiuti:

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
}

Il metodo chiama qui e trasmette il valore datetime (MM / gg / aaaa se il server è impostato sulla locale USA). Sostituiscilo con qualunque cosa sia un messagebox o qualsiasi container da visualizzare:

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

Ricorda che puoi formattare il messaggio come preferisci.


14

Che ne dici di questa soluzione?

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

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

10

Il seguente approccio (estratto da Time Period Library per .NET class DateDiff ) considera il calendario delle informazioni sulla 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 )
    {
      compareDate = compareDate.AddYears( 1 );
    }
  }
  else
  {
    if ( compareDate > date1 )
    {
      compareDate = compareDate.AddYears( -1 );
    }
  }
  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

10

Questa classica domanda merita una soluzione 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);

Potresti anche essere interessato ai seguenti miglioramenti:

  • Passare l'orologio come IClock, invece di usare SystemClock.Instance, migliorerebbe la testabilità.

  • Il fuso orario target probabilmente cambierà, quindi vorresti anche un DateTimeZoneparametro.

Vedi anche il mio post sul blog su questo argomento: Gestione dei compleanni e altri anniversari


Sei affiliato con Noda Time?
Zimano,

Ci ho dato un contributo, ma è principalmente di Jon Skeet.
Matt Johnson-Pint,

9

Ho usato la soluzione di ScArcher2 per un accurato calcolo dell'anno dell'età di una persona, ma dovevo prenderla ulteriormente e calcolare i loro mesi e giorni insieme agli anni.

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

9

Versione 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  

8

Ho apportato una piccola modifica alla risposta di Mark Soen : ho riscritto la terza riga in modo che l'espressione possa essere analizzata un po 'più facilmente.

public int AgeInYears(DateTime bday)
{
    DateTime now = DateTime.Today;
    int age = now.Year - bday.Year;            
    if (bday.AddYears(age) > now) 
        age--;
    return age;
}

L'ho anche trasformato in una funzione per motivi di chiarezza.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.