Pytanie Jak obliczyć czyjś wiek w C #?


Dawać DateTime reprezentujących urodziny danej osoby, jak obliczyć ich wiek w latach?


1744


pochodzenie


to, czego dotychczas brakowało wszystkim odpowiedziom, zależy od miejsca urodzenia i miejsca, w którym się znajdują. - Yaur
@ Yaur: Po prostu przelicz czas teraz + narodziny na GMT / UTC, wiek jest tylko względną wartością, dlatego strefy czasowe są nieistotne. Aby określić aktualną strefę czasową użytkownika, możesz użyć funkcji GeoLocating. - Stefan Steiger
Dlaczego nie rozważyć [Julian Date] [1]? [1]: stackoverflow.com/questions/7103064/... - Muhammad Hewedy
Jeśli weźmiemy pod uwagę sugestię @ Yaura obliczania strefy czasowej, czy w świetle dziennym powinien on w jakikolwiek sposób wpływać na obliczenia? - DDM
Nikt nie rozważał lat przestępnych? lub sprawdzanie miesiąca? - Crash Override


Odpowiedzi:


Łatwe do zrozumienia i proste rozwiązanie.

// Save today's date.
var today = DateTime.Today;
// Calculate the age.
var age = today.Year - birthdate.Year;
// Go back to the year the person was born in case of a leap year
if (birthdate > today.AddYears(-age)) age--;

Jednak to zakłada, że ​​szukasz western idea wieku i nieużywania Rachunki wschodnioazjatyckie.


1721



Chciałem tylko skomentować DateTime.Now wydajność. Jeśli nie potrzebujesz dokładnej wartości strefy czasowej, użyj funkcji DateTime.UtcNow, która jest znacznie szybsza. - JAG
Biorąc pod uwagę, że mówimy o urodzinach, możesz po prostu użyć DateTime.Today, biorąc pod uwagę część czasu nie ma znaczenia. - Tristan Warner-Smith
Ta odpowiedź nie działa ze wszystkimi ustawieniami regionalnymi i dla wszystkich grup wiekowych. Kilka krajów pominęło daty po narodzinach obecnych żyjących ludzi, w tym w Rosji (1918 r.), Grecji (1924 r.) I Turcji (1926 r.). - Lars D
W rzeczywistości wciąż nie jest to całkowicie poprawne. Ten kod zakłada, że ​​"bday" jest datą porcji DateTime. Jest to przypadek skrajny (myślę, że większość ludzi będzie tylko podawać daty, a nie daty i godziny), ale jeśli przekażesz urodziny jako datę i godzinę, gdzie czas jest dłuższy niż 00:00:00, to jesteś " Natkną się na błąd, na który zwrócił uwagę Danvil. Ustawienie bday = bday.Date to rozwiązuje. - Øyvind
Ostatnia linia sprawiła, że ​​pomyślałem zbyt wiele. Zamiast tego: o: if (bday.AddYears (age)> now) age--; Wydaje się to być bardziej intuicyjnym wyrażeniem. - cdiggins


To dziwny sposób, ale jeśli sformatujesz datę na yyyymmdd i odejmij datę urodzenia od bieżącej daty, a następnie upuść 4 ostatnie cyfry, które masz w danym wieku :)

Nie znam C #, ale wierzę, że to zadziała w dowolnym języku.

20080814 - 19800703 = 280111 

Usuń ostatnie 4 cyfry = 28.

Kod C #:

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

Lub alternatywnie bez całej konwersji typu w postaci metody rozszerzenia. Podczas sprawdzania błędu pominięto:

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

894



Horray dla yyyymmdd. Pierwszy produkt bazy danych użyty na POsobisty doomputer (około 1981) zapisał daty w tym formacie. Manipulowanie datami było o wiele łatwiejsze. - radarbob
W rzeczywistości jest to świetne do użycia w MS-SQL z datetime-fields (całkowita liczba dni od 01-011900) - Patrik Eckebrecht
@numerek Opublikuj sugerowane modyfikacje jako własną odpowiedź. Co warte jest, że czasy w roku bieżącym wynoszą 10000, a więc nie są w pobliżu przepełnienia liczby całkowitej, o dwa rzędy wielkości. 20 150 000 wobec 2 147 483 648 - GalacticCowboy
@LongChalk 20180101 - 20171231 = 8870. Usuń ostatnie 4 cyfry i masz (domyślnie) 0 na wiek. Jak dostałeś 1? - Rufus L
@flindeberg Tak, właśnie to mówiłem do LongChalk ... - Rufus L


Nie wiem, jak można przyjąć niewłaściwe rozwiązanie. Prawidłowy fragment C # został napisany przez Michaela Stuma

Oto fragment testowy:

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

Tutaj masz metody:

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

345



Wynik: -Test 9 9 8 - MoXplod
Chociaż ten kod działa, twierdzi, że osoba urodzona w dniu przestępnym osiąga kolejny rok życia w dniu nieskrępowania, a nie w dniu 28 lutego. W rzeczywistości, każda opcja może być poprawna. Wikipedia ma coś do powiedzenia na ten temat. Tak więc, chociaż twój kod nie jest "zły", żadne z tych rozwiązań nie jest akceptowane. - Matt Johnson
@MattJohnson Myślę, że to jest poprawne. Jeśli moje urodziny miały miejsce 29 lutego, to 28 lutego moje urodziny nie minęły, a ja powinienem być w tym samym wieku co 27 ​​lutego. Jednak 1 marca minęło moje bday i powinienem być w następnym wieku. W Stanach Zjednoczonych firma, która sprzedaje alkohol, będzie oznaczona napisem "Jeśli urodziłeś się po tym dniu w YYYY, nie możesz kupić alkoholu" (gdzie YYYY zmienia się co roku). Oznacza to, że ktoś urodzony 29 lutego nie może kupić alkoholu 28 lutego w roku, w którym skończy 21 lat (większość miejsc), i popiera pogląd, że nie są one rok starsze, aż do 1 marca. - jfren484
@ jfren484 - przeczytaj artykuł w Wikipedii. Różni się znacznie w różnych jurysdykcjach. - Matt Johnson
@ jfren484 Twoje twierdzenie nie ma absolutnie nic wspólnego z filozofią; ale wszystko z tym związane twoje własne osobiste uczucie. Gdy osoba urodzona w dniu 29 lutego "w wieku" jest w dużej mierze nieważna, chyba że wiek stanowi "prawną granicę wieku" (np. Czy można kupić alkohol, głosować, uzyskać emeryturę, dołączyć do wojska, uzyskać prawo jazdy). Rozważmy wiek picia w USA (21 lat): dla większości osób jest to 7670 dni. Jest 7671 dni, jeśli urodzony przed 29 lutego w roku przestępnym lub 1 marca przed rokiem przestępnym. Jeśli urodzony 29 lutego: 28 lutego to 7670 dni, a 1 marca 7671 dni. Wybór jest arbitralny może iść w obie strony. - Craig Young


Nie sądzę, aby jakakolwiek z dotychczasowych odpowiedzi dotyczyła kultur, które obliczałyby wiek inaczej. Zobacz na przykład East Age Reckoning wieku w porównaniu do tego na Zachodzie.

Każdy real odpowiedź musi zawierać lokalizację. The Wzór strategii prawdopodobnie będzie w tym przykładzie.


115



Z artykułu wikipedii, który dostarczyłeś: "W Chinach i Japonii jest używany do tradycyjnego wróżenia lub religii i znika w codziennym życiu między ludźmi w mieście." - some
@some - Koreańczycy nadal używają tego systemu przede wszystkim. - Justin L.
W rzeczywistości ta koncepcja może być bardzo ważna - ludzie nie lubią, gdy ich dane osobowe są niewłaściwie podawane. Na przykład połowa mojej rodziny mieszka w Malezji, a połowa w Wielkiej Brytanii. W tej chwili mój wiek jest uważany za dwa lata wyższy, gdy jestem z jednej strony mojej rodziny, niż z drugą. - Phil Gan
Nie tylko my używamy tego systemu przede wszystkim w Korei, ale jako turysta, który omawia wieki z mieszkańcami, miejscowi grzecznie odnoszą się do siebie nawzajem w roku urodzenia. Nie mam 25 lat, mam 87 lat. Podobało mi się to podejście lepiej. więcej "międzynarodowego formatu daty urodzenia" - Dean Rather
W Wietnamie, w życiu codziennym, nawet jeśli używany jest system zachodni, wiek oblicza się jedynie przez odjęcie lat. Data jest wykluczona - phuclv


Prostą odpowiedzią na to jest zastosowanie AddYears jak pokazano poniżej, ponieważ jest to jedyna natywna metoda dodawania lat do 29 lutego lat przestępnych i uzyskania prawidłowego wyniku z 28 lutego dla wspólnych lat.

Niektórzy uważają, że 1 marca to urodziny skoków, ale ani .Net, ani żadna oficjalna reguła tego nie popierają, ani też powszechna logika nie wyjaśnia, dlaczego niektórzy urodzeni w lutym powinni mieć 75% swoich urodzin w kolejnym miesiącu.

Ponadto, metoda Age może zostać dodana jako rozszerzenie DateTime. W ten sposób możesz uzyskać wiek w najprostszy możliwy sposób:

  1. Element listy

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

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

Przykład krytycznej daty jest następujący:

Data urodzenia: 2000-02-29 Późniejsza data: 2011-02-28 Wiek: 11

Wydajność:

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

I na późniejszą datę 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
}

99



Komentarz dotyczący obchodów 29 lutego w dniu 1 marca, technicznie rzecz biorąc, 28 dnia jest zbyt wcześnie (tak naprawdę 1 dzień wcześniej). 1 dnia to jeden dzień za późno. Ale ponieważ urodziny są pomiędzy, używanie 1. do obliczania wieku w latach bez skoku ma dla mnie więcej sensu, ponieważ ta osoba jest rzeczywiście tak stara 1 marca (i 2 i 3) każdego roku, ale nie w dniu 28 lutego. - CyberClaw


Moja sugestia

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

Wydaje się, że ten rok zmienia się we właściwym czasie. (Sprawdzam testy do wieku 107 lat)


76



Skąd pochodzi 365.255? Nie sądzę, że to będzie działać ogólnie. - dreeves
365 dni w roku. +0,25 dla lat przestępnych. +0,005 za inne poprawki - James Curran
Nie sądzę, żeby Harry Patch docenił twoją metodologię testów na miejscu: latimes.com/news/obituaries/... - MusiGenesis
Średnia długość roku w kalendarzu gregoriańskim to 365.2425 dni. - dan04
^^ Bo czasami jest to ważne. W moich testach kończy się to niepowodzeniem w dniu urodzin osób, informuje, że są młodsi niż oni. - ChadT


Kolejna funkcja, nie przeze mnie, ale znaleziona w sieci i udoskonalona nieco:

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

Tylko dwie rzeczy, które przychodzą mi do głowy: co z ludźmi z krajów, które nie korzystają z kalendarza gregoriańskiego? DateTime.Now jest w kulturze specyficznej dla serwera, myślę. Mam absolutnie 0 wiedzy na temat pracy z azjatyckimi kalendarzami i nie wiem, czy istnieje prosty sposób na konwersję dat między kalendarzami, ale na wypadek, gdybyś zastanawiał się nad tymi chińskimi chłopakami z roku 4660 :-)


65



Wydaje się, że najlepiej radzi sobie z różnymi regionami (formatami dat). - webdad3