ใน C # ฉันจะคำนวณอายุของใครบางคนตามวันเกิดของประเภท DateTime ได้อย่างไร


1867

ได้รับDateTimeเป็นตัวแทนวันเกิดของคนที่ฉันจะคำนวณอายุของพวกเขาในปี?


147
สิ่งที่คำตอบทั้งหมดที่พลาดไปนั้นขึ้นอยู่กับว่าบุคคลนั้นเกิดที่ไหนและตอนนี้อยู่ที่ไหน
Yaur

40
@Yaur: เพียงแค่แปลงเวลาในขณะนี้ + เกิดเป็น GMT / UTC อายุเป็นเพียงค่าสัมพัทธ์ดังนั้นเขตเวลาจะไม่เกี่ยวข้อง สำหรับการกำหนดเขตเวลาปัจจุบันของผู้ใช้คุณสามารถใช้ GeoLocating
Stefan Steiger

ทำไมไม่ลองพิจารณา [Julian Date] [1] [1]: stackoverflow.com/questions/7103064/ …
Muhammad Hewedy

5
หากเรากำลังพิจารณาข้อเสนอแนะของ @Yaur เกี่ยวกับการคำนวณข้ามเขตเวลาควรปรับเวลาแสงกลางวันมีผลต่อการคำนวณในลักษณะใดหรือไม่?
DDM

6
ลงเนื่องจากนี่เป็นคำถามการบ้านอย่างชัดเจนและไม่มีการพยายามที่มีอยู่
Marie

คำตอบ:


2122

วิธีแก้ปัญหาที่เข้าใจง่ายและเรียบง่าย

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

แต่นี้จะถือว่าคุณกำลังมองหาตะวันตกความคิดของอายุและไม่ได้ใช้การคำนวณเอเชียตะวันออก


252
เพียงแค่ต้องการที่จะแสดงความคิดเห็นเกี่ยวกับประสิทธิภาพ DateTime ตอนนี้ หากคุณไม่ต้องการค่าเขตเวลาที่ถูกต้องให้ใช้ DateTimeUtcNow รวดเร็วยิ่งขึ้น
JAG

104
ให้เรากำลังพูดถึงวันเกิดคุณสามารถใช้ DateTime วันนี้รับส่วนเวลาไม่มีความเกี่ยวข้อง
Tristan Warner-Smith

78
คำตอบนี้ไม่สามารถใช้ได้กับทุกสถานที่และทุกวัย หลายประเทศได้ข้ามวันหลังจากการเกิดของคนที่มีชีวิตในปัจจุบันรวมถึงรัสเซีย (1918), กรีซ (1924) และตุรกี (1926)
Lars D

30
จริงๆแล้วมันยังไม่ถูกต้องทั้งหมด รหัสนี้อนุมานว่า 'bday' เป็นส่วนของ DateTime เป็นกรณีขอบ (ฉันเดาว่าคนส่วนใหญ่เพิ่งจะผ่านวันที่และไม่ใช่วันที่ - เวลา) แต่ถ้าคุณผ่านวันเกิดเป็นวันและเวลาที่เวลามากกว่า 00:00:00 จะพบข้อผิดพลาด Danvil ชี้ให้เห็น การตั้งค่า bday = bday.Date แก้ไขสิ่งนี้
Øyvind

119
บรรทัดสุดท้ายทำให้ฉันคิดมากเกินไป แต่จะเป็นอย่างไรถ้า: (bday.AddYears (อายุ)> ตอนนี้) อายุ -; ดูเหมือนว่าจะเป็นการแสดงออกที่เข้าใจง่ายกว่า
cdiggins

1015

นี่เป็นวิธีที่แปลกที่จะทำ แต่ถ้าคุณจัดรูปแบบวันที่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;
}

5
ที่จริงแล้วนี่เป็นสิ่งที่ยอดเยี่ยมสำหรับการใช้งานบน MS-SQL ที่มีเขตข้อมูลและเวลา (รวมวันตั้งแต่ 01-011900)
Patrik

5
@numerek โปรดโพสต์การดัดแปลงที่แนะนำของคุณเป็นคำตอบของพวกเขาเอง สำหรับสิ่งที่คุ้มค่าปีปัจจุบันที่ 10,000 ไม่มีที่ไหนเลยใกล้กับจำนวนเต็มล้นด้วยคำสั่งสองขนาด 20,150,000 vs 2,147,483,648
GalacticCowboy

7
20180101 - 20171231 = 8870@LongChalk วางตัวเลข 4 หลักสุดท้ายและคุณมี (โดยนัย) 0สำหรับอายุ คุณได้1อย่างไร
รูฟัส L

4
ฉันรู้ว่านี่เป็นคำตอบเก่า แต่ฉันจะไม่ทำวิธีการขยายออกจากมันไม่ใช่สถานที่ที่เหมาะสมในการกำหนด logics ดังกล่าว
Lucca Ferri

1
คาถาอะไรแบบนี้?
Muleskinner

391

นี่คือตัวอย่างข้อมูลการทดสอบ:

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

ที่นี่คุณมีวิธีการ:

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
ในขณะที่รหัสนี้ใช้งานได้มันก็อ้างว่าคนที่เกิดในวันอธิกสุรทินบรรลุถึงปีถัดไปของวันที่ 1 มีนาคมในปีที่ไม่ก้าวกระโดดมากกว่าในวันที่ 28 กุมภาพันธ์ ในความเป็นจริงตัวเลือกอย่างใดอย่างหนึ่งอาจจะเป็นที่ถูกต้อง วิกิพีเดียมีสิ่งที่จะพูดเกี่ยวกับเรื่องนี้ ดังนั้นแม้ว่ารหัสของคุณจะไม่ "ผิด" แต่ก็ไม่ใช่วิธีที่ยอมรับได้
Matt Johnson-Pint

18
@ MattJohnson ฉันคิดว่ามันถูกต้องจริง ถ้า bday ของฉันคือ 29 กุมภาพันธ์จากนั้น 28 กุมภาพันธ์ bday ของฉันจะไม่ผ่านและฉันก็ควรจะอายุเท่ากันในวันที่ 27 กุมภาพันธ์อย่างไรก็ตามในวันที่ 1 มีนาคมอย่างไรก็ตามเราได้ผ่าน bday ของฉันแล้วและฉันควรจะเป็นคนต่อไป ในสหรัฐอเมริกาธุรกิจที่ขายเครื่องดื่มแอลกอฮอล์จะมีป้ายบอกว่า "ถ้าคุณเกิดหลังจากวันนี้ใน YYYY คุณไม่สามารถซื้อเครื่องดื่มแอลกอฮอล์ได้" (ที่ YYYY เปลี่ยนแปลงทุกปี) นั่นหมายความว่าคนที่เกิดในวันที่ 29 กุมภาพันธ์ไม่สามารถซื้อเครื่องดื่มแอลกอฮอล์ได้ในวันที่ 28 กุมภาพันธ์ในปีที่พวกเขาอายุ 21 ปี (สถานที่ส่วนใหญ่) และให้การสนับสนุนแนวคิดที่ว่าพวกเขาจะไม่แก่กว่าหนึ่งปีจนถึง 1 มีนาคม
jfren484

4
@ jfren484 - อ่านบทความ Wikipedia มันแตกต่างกันมากในเขตอำนาจศาล
Matt Johnson-Pint

9
@ jfren484 การเรียกร้องของคุณไม่มีอะไรเกี่ยวข้องกับปรัชญาอย่างแน่นอน แต่ทุกอย่างจะทำอย่างไรกับความรู้สึกส่วนตัวของคุณเอง เมื่อบุคคลที่เกิดในวันที่ 29 กุมภาพันธ์ "อายุ" ส่วนใหญ่ไม่สำคัญเว้นแต่อายุจะเป็น 'ขอบเขตอายุทางกฎหมาย' (เช่นสามารถซื้อเครื่องดื่มแอลกอฮอล์ลงคะแนนเสียงรับเงินบำนาญเข้าร่วมกองทัพรับใบขับขี่) พิจารณาอายุการดื่มของสหรัฐอเมริกา (21 ปี): สำหรับคนส่วนใหญ่นั่นคือ 7670 วัน มันคือ 7671 วันถ้าเกิดก่อน 29 กุมภาพันธ์ในปีอธิกสุรทินหรือจาก 1 มีนาคมก่อนปีอธิกสุรทิน หากเกิดวันที่ 29 กุมภาพันธ์: 28 กุมภาพันธ์คือ 7670 วันและ 1 มีนาคมคือ 7671 วัน ตัวเลือกนั้นสามารถใช้ได้ทั้งสองทาง
ไม่แยแส

4
@CraigYoung คุณไม่เข้าใจสิ่งที่ฉันหมายถึงปรัชญา ฉันใช้คำนั้นตรงกันข้ามกับกฎหมาย หากมีใครกำลังเขียนแอปพลิเคชันที่จำเป็นต้องรู้อายุทางกฎหมายของบุคคลดังนั้นสิ่งที่พวกเขาต้องรู้คือเขตอำนาจศาลทางกฎหมายว่าแอปพลิเคชันของพวกเขาถูกนำมาใช้ใน / เพื่อรักษาผู้ที่เกิดในวันที่ 29 กุมภาพันธ์อย่างไร พูดคุยเกี่ยวกับวิธีการที่ควรได้รับการปฏิบัติแล้วตามนิยามปรัชญา และใช่ความเห็นที่ฉันให้นั้นเป็นความเห็นของฉันเอง แต่อย่างที่ฉันพูดฉันคิดว่ามันจะง่ายกว่าที่จะโต้แย้งในวันที่ 1 มีนาคมกว่าจะเป็นวันที่ 28 กุมภาพันธ์
jfren484

109

คำตอบง่ายๆนี้คือการใช้งานAddYearsดังที่แสดงไว้ด้านล่างเพราะนี่เป็นวิธีการเดียวที่จะเพิ่มปีในวันที่ 29 กุมภาพันธ์ของปีอธิกสุรทินและได้รับผลลัพธ์ที่ถูกต้องของวันที่ 28 กุมภาพันธ์สำหรับปีทั่วไป

บางคนรู้สึกว่าวันที่ 1 มีนาคมเป็นวันเกิดของ leaplings แต่ไม่ใช่. Net หรือกฎอย่างเป็นทางการใด ๆ ที่สนับสนุนเรื่องนี้และตรรกะทั่วไปไม่อธิบายว่าทำไมคนที่เกิดในเดือนกุมภาพันธ์ควรมี 75% ของวันเกิดของพวกเขาในเดือนอื่น

DateTimeนอกจากนี้วิธีการที่อายุยืมตัวเองที่จะเพิ่มเป็นส่วนขยายไป ด้วยวิธีนี้คุณสามารถรับอายุด้วยวิธีที่ง่ายที่สุดที่เป็นไปได้:

  1. รายการสินค้า

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

ตอนนี้รันการทดสอบนี้:

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
}

4
ความคิดเห็นเกี่ยวกับการมีวันคล้ายวันเกิด 29 กุมภาพันธ์ในวันที่ 1 มีนาคมในทางเทคนิคการมีวันที่ 28 กุมภาพันธ์นั้นเร็วเกินไป (จริง ๆ แล้ว 1 วันก่อนหน้า) ในวันที่หนึ่งคือวันหนึ่งสายเกินไป แต่เนื่องจากวันเกิดอยู่ระหว่างการใช้วันที่ 1 ในการคำนวณอายุในแบบไม่ก้าวกระโดดทำให้ฉันมีเหตุผลมากกว่าเพราะคน ๆ นั้นอายุมากในวันที่ 1 มีนาคม (และ 2 และ 3) ทุกปี แต่ไม่ใช่ในวันที่ 28 กุมภาพันธ์
CyberClaw

1
จากจุดการออกแบบซอฟต์แวร์การเขียนนี้เป็นวิธีการขยายไม่สมเหตุสมผลสำหรับฉัน date.Age(other)?
marsze

90

คำแนะนำของฉัน

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

ดูเหมือนว่าจะมีการเปลี่ยนแปลงปีในวันที่ถูกต้อง (ฉันเห็นการทดสอบจนถึงอายุ 107 แล้ว)


26
ฉันไม่คิดว่า Harry Patch จะพอใจกับวิธีการทดสอบจุดของคุณ: latimes.com/news/obituaries/ …
MusiGenesis

3
Google กล่าวว่าdays in a year = 365.242199
mpen

12
ระยะเวลาเฉลี่ยหนึ่งปีในปฏิทินเกรกอเรียนคือ 365.2425 วัน
dan04

4
ผมจะบอกว่านี้เป็นหนึ่งในวิธีการที่ง่ายที่สุดและเป็นที่ดีพอ ใครจะเป็นห่วงถ้าฉันครึ่งวันก่อนวันเกิดปีที่สิบ X ของฉันและโปรแกรมบอกว่าฉันอายุ X โปรแกรมมีสิทธิ์มากหรือน้อยแม้ว่าจะไม่ใช่เชิงคณิตศาสตร์ก็ตาม ฉันชอบวิธีนี้มาก
Peter Perháč

13
^^ เพราะบางครั้งมันสำคัญ ในการทดสอบของฉันสิ่งนี้ล้มเหลวในวันเกิดของบุคคลมันรายงานว่าพวกเขาอายุน้อยกว่าพวกเขา
ChadT

76

ฟังก์ชั่นอื่นไม่ใช่โดยฉัน แต่พบได้บนเว็บและขัดเกลา:

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


สิ่งนี้ดูเหมือนว่าจะจัดการกับภูมิภาคต่างๆ (รูปแบบวันที่) ที่ดีที่สุด
webdad3

53

2 ปัญหาหลักในการแก้ไขคือ:

1. คำนวณอายุที่แน่นอน - ในปีเดือนวัน ฯลฯ

2. คำนวณอายุที่รับรู้โดยทั่วไป - ผู้คนมักจะไม่สนใจว่าพวกเขามีอายุเท่าไรพวกเขาแค่สนใจเมื่อวันเกิดของพวกเขาในปีปัจจุบัน


โซลูชันสำหรับ1ชัดเจน:

DateTime birth = DateTime.Parse("1.1.2000");
DateTime today = DateTime.Today;     //we usually don't care about birth time
TimeSpan age = today - birth;        //.NET FCL should guarantee this as precise
double ageInDays = age.TotalDays;    //total number of days ... also precise
double daysInYear = 365.2425;        //statistical value for 400 years
double ageInYears = ageInDays / daysInYear;  //can be shifted ... not so precise

วิธีแก้ปัญหาสำหรับ2เป็นวิธีที่ไม่แม่นยำในการยับยั้งอายุรวม แต่ถูกมองว่าเป็นคนที่แม่นยำ ผู้คนมักจะใช้มันเมื่อพวกเขาคำนวณอายุ "ด้วยตนเอง":

DateTime birth = DateTime.Parse("1.1.2000");
DateTime today = DateTime.Today;
int age = today.Year - birth.Year;    //people perceive their age in years

if (today.Month < birth.Month ||
   ((today.Month == birth.Month) && (today.Day < birth.Day)))
{
  age--;  //birthday in current year not yet reached, we are 1 year younger ;)
          //+ no birthday for 29.2. guys ... sorry, just wrong date for birth
}

หมายเหตุถึง 2:

  • นี่คือทางออกที่ฉันต้องการ
  • เราไม่สามารถใช้ DateTime.DayOfYear หรือ 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);
}

50

นี่คือหนึ่งซับ:

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

23
นี่มันหัก ทำแบบทดสอบได้: public static int CalculateAge (DateTime dateOfBirth, DateTime dateCalculateAge) {ส่งคืน DateTime ใหม่ (dateToCalculateAge.Subtract (dateOfBirth) .Ticks) ปีที่แล้ว - 1; } ... ให้อายุ 14 เมื่อฉันป้อนข้อมูล 1990-06-01 และคำนวณอายุในวันก่อนวันเกิดปีที่ 14 ของเขา (1990-05-31)
Kjensen

43

นี่คือรุ่นที่เราใช้ที่นี่ มันใช้งานได้และมันค่อนข้างง่าย มันเป็นความคิดเดียวกับของ Jeff แต่ฉันคิดว่ามันชัดเจนขึ้นเล็กน้อยเพราะมันแยกตรรกะสำหรับการลบออกดังนั้นจึงเข้าใจง่ายขึ้นเล็กน้อย

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

คุณสามารถขยายผู้ประกอบการที่ประกอบไปด้วยเพื่อให้ชัดเจนยิ่งขึ้นถ้าคุณคิดว่าสิ่งนั้นไม่ชัดเจน

เห็นได้ชัดว่านี่เป็นวิธีส่วนขยายDateTimeแต่คุณสามารถคว้าโค้ดหนึ่งบรรทัดที่ใช้งานได้และวางไว้ที่ใดก็ได้ ที่นี่เรามี overload อีกวิธีการขยายที่ผ่านDateTime.Nowเพียงเพื่อความสมบูรณ์


6
ฉันคิดว่าสิ่งนี้สามารถปิดได้ในวันเดียวเมื่อวันหนึ่งในวันเกิดวันเกิดหรือวันที่ตรงกับปีอธิกสุรทิน พิจารณาอายุของบุคคลที่เกิดในวันที่ 1 มีนาคม 2546 ในวันที่ 29 กุมภาพันธ์ 2547 เพื่อแก้ไขสิ่งนี้คุณต้องทำการเปรียบเทียบพจนานุกรม (เดือน, DayOfMonth) และใช้คู่กับเงื่อนไข
Doug McClean

1
มันจะไม่แสดงอายุที่เหมาะสมในวันเกิดของคุณด้วย
dotjoe

43

วิธีที่ดีที่สุดที่ฉันรู้เพราะปีอธิกสุรทินและทุกอย่างคือ:

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

34

ฉันใช้สิ่งนี้:

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

สิ่งนี้ให้ "รายละเอียดเพิ่มเติม" สำหรับคำถามนี้ บางทีนี่อาจเป็นสิ่งที่คุณกำลังมองหา

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
สิ่งนี้ไม่ทำงานตลอดเวลา การเพิ่มช่วงลงใน DateTime.MinValue อาจทำงานได้โดยไม่ต้องมีบัญชีสำหรับ leap ปีเป็นต้นหากคุณเพิ่มปีเดือนและวันที่ให้แก่ Age โดยใช้ฟังก์ชัน AddYears (), AddMonths และ AddDays () จะไม่ส่งคืน Datetime ทุกครั้ง . วันนี้
Athanasios Kataras

3
เวลาตัวเองใช้เวลาในการพิจารณาเผ่นปีโดยอัตโนมัติระหว่าง 2 วันดังนั้นฉันไม่แน่ใจว่าสิ่งที่คุณได้รับเกี่ยวกับ ฉันได้ถามในฟอรัม microsoft และ microsoft ได้ยืนยันว่าจะใช้เวลาในการข้ามปีระหว่าง 2 วัน
Jacqueline Loriault

2
พิจารณา Senarios สองต่อไปนี้ 1st DateTime ตอนนี้คือ 1/1/2544 และลูกเกิดวันที่ 1/1/2000 2000 เป็นปีอธิกสุรทินและผลลัพธ์จะเป็น 1 ปี 0 เดือนและ 1 วัน ใน SenTime ที่สอง DateTime ขณะนี้คือ 1/1/2545 และเด็กนั้นจะเกิดในวันที่ 1/1/2544 ในกรณีนี้ผลลัพธ์จะเป็น 1 ปี 0 เดือนและ 0 วัน ที่จะเกิดขึ้นเพราะคุณกำลังเพิ่มช่วงเวลาในปีที่ไม่ก้าวกระโดด ถ้า DateTime.MinValue เป็นปีอธิกสุรทินผลลัพธ์จะเป็น 1 ปีในช่วงแรกและ 0 ปี 11 เดือนและ 30 วัน (ลองในรหัสของคุณ)
Athanasios Kataras

1
Upvote! ฉันคิดวิธีแก้ปัญหาที่ค่อนข้างเหมือนกัน (ฉันใช้ DateTime.MinValue.AddTicks (span.Ticks) แทนที่จะเป็น + แต่ผลลัพธ์เหมือนกันและผลลัพธ์ของคุณมีรหัสน้อยกว่าเล็กน้อย)
Makotosan

4
คุณพูดถูก แต่ถ้าเป็นเช่นนั้นก็จะเป็นผล ทำไมมันถึงสำคัญ? มันไม่ได้ ในกรณีที่กระโดดหรือไม่นั้นมีตัวอย่างที่ไม่ทำงาน นั่นคือสิ่งที่ฉันต้องการแสดง DIFF นั้นถูกต้อง Span คำนึงถึงปีอธิกสุรทิน แต่การเพิ่มวันที่พื้นฐานไม่ใช่ ลองตัวอย่างในรหัสและคุณจะเห็นว่าฉันถูก
Athanasios Kataras

28

ฉันได้สร้างฟังก์ชั่นที่กำหนดโดยผู้ใช้ของเซิร์ฟเวอร์ SQL เพื่อคำนวณอายุของใครบางคนโดยกำหนดวันเกิดของพวกเขา สิ่งนี้มีประโยชน์เมื่อคุณต้องการเป็นส่วนหนึ่งของแบบสอบถาม:

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

นี่คือคำตอบอื่น:

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

สิ่งนี้ได้รับการทดสอบอย่างกว้างขวาง มันมีลักษณะ "วิเศษ" เล็กน้อย หมายเลข 372 คือจำนวนวันในหนึ่งปีหากทุกเดือนมี 31 วัน

ชี้แจงทำไมมันทำงาน ( ยกมาจากที่นี่ ) เป็น:

มาตั้งกันเถอะ Yn = DateTime.Now.Year, Yb = birthday.Year, Mn = DateTime.Now.Month, Mb = birthday.Month, Dn = DateTime.Now.Day, Db = birthday.Day

age = Yn - Yb + (31*(Mn - Mb) + (Dn - Db)) / 372

เรารู้ว่าสิ่งที่เราต้องการก็คือYn-Ybถ้าวันที่ได้ไปถึงแล้วYn-Yb-1ถ้ามันไม่ได้

a) ถ้าMn<Mbเรามี-341 <= 31*(Mn-Mb) <= -31 and -30 <= Dn-Db <= 30

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

ด้วยการหารจำนวนเต็ม

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

b) ถ้าMn=MbและDn<Dbเรามี31*(Mn - Mb) = 0 and -30 <= Dn-Db <= -1

ด้วยการหารจำนวนเต็มอีกครั้ง

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

c) ถ้าMn>Mbเรามี31 <= 31*(Mn-Mb) <= 341 and -30 <= Dn-Db <= 30

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

ด้วยการหารจำนวนเต็ม

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

d) ถ้าMn=MbและDn>Dbเรามี31*(Mn - Mb) = 0 and 1 <= Dn-Db <= 30

ด้วยการหารจำนวนเต็มอีกครั้ง

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

e) ถ้าMn=MbและDn=Dbเรามี31*(Mn - Mb) + Dn-Db = 0

และดังนั้นจึง (31*(Mn - Mb) + (Dn - Db)) / 372 = 0


3
ฉันสะดุดกับการสนทนาที่ยาวนานและน่ารำคาญและโซลูชันของคุณเป็นวิธีการที่ดีและเล็กมาก ขอบคุณที่ทำให้มันง่าย
nabuchodonossor

25

ฉันใช้เวลาทำงานนี้แล้วคิดสิ่งนี้เพื่อคำนวณอายุของใครบางคนในปีเดือนและวัน ฉันได้ทดสอบกับปัญหาที่ 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++;
    }

}

21

เราจำเป็นต้องพิจารณาคนที่อายุน้อยกว่า 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);
}

หวังว่ามันจะเป็นประโยชน์


20

ทำให้มันง่าย (และอาจโง่ :))

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 เป็นตัวเลือกแรกของฉัน แต่พบว่ามันไม่มีคุณสมบัติ TotalYears คุณสามารถลอง (ts.TotalDays / 365) - แต่มันไม่นับเป็นปีอธิกสุรทิน ฯลฯ
Lazlow

19

วิธีที่ง่ายที่สุดที่ฉันเคยพบคือ มันทำงานได้อย่างถูกต้องสำหรับสถานที่ในสหรัฐอเมริกาและยุโรปตะวันตก ไม่สามารถพูดคุยกับสถานที่อื่น ๆ โดยเฉพาะสถานที่เช่นจีน เปรียบเทียบ 4 พิเศษมากที่สุดตามการคำนวณเริ่มต้นของอายุ

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

ฉันกำลังค้นหาคำตอบสำหรับสิ่งนี้และสังเกตเห็นว่าไม่มีใครอ้างอิงถึงผลกระทบด้านกฎระเบียบ / กฎหมายของการเกิดวันอธิกสุรทิน ตัวอย่างเช่นตาม Wikipediaถ้าคุณเกิดวันที่ 29 กุมภาพันธ์ในเขตอำนาจศาลที่หลากหลาย

  • ในสหราชอาณาจักรและฮ่องกง: มันเป็นวันที่ของปีดังนั้นวันถัดไปวันที่ 1 มีนาคมเป็นวันเกิดของคุณ
  • ในนิวซีแลนด์: เป็นวันก่อนหน้าวันที่ 28 กุมภาพันธ์สำหรับวัตถุประสงค์ในการออกใบขับขี่และวันที่ 1 มีนาคมสำหรับวัตถุประสงค์อื่น
  • ไต้หวัน: วันที่ 28 กุมภาพันธ์

และใกล้ที่สุดเท่าที่ฉันจะบอกได้ว่าในสหรัฐอเมริกากฎเกณฑ์นั้นเงียบในเรื่องนี้ปล่อยให้เป็นไปตามกฎหมายและวิธีการที่หน่วยงานกำกับดูแลต่างๆกำหนดสิ่งต่าง ๆ ไว้ในข้อบังคับ

ด้วยเหตุนี้การปรับปรุง:

public enum LeapDayRule
{
  OrdinalDay     = 1 ,
  LastDayOfMonth = 2 ,
}

static int ComputeAgeInYears(DateTime birth, DateTime reference, LeapYearBirthdayRule ruleInEffect)
{
  bool isLeapYearBirthday = CultureInfo.CurrentCulture.Calendar.IsLeapDay(birth.Year, birth.Month, birth.Day);
  DateTime cutoff;

  if (isLeapYearBirthday && !DateTime.IsLeapYear(reference.Year))
  {
    switch (ruleInEffect)
    {
      case LeapDayRule.OrdinalDay:
        cutoff = new DateTime(reference.Year, 1, 1)
                             .AddDays(birth.DayOfYear - 1);
        break;

      case LeapDayRule.LastDayOfMonth:
        cutoff = new DateTime(reference.Year, birth.Month, 1)
                             .AddMonths(1)
                             .AddDays(-1);
        break;

      default:
        throw new InvalidOperationException();
    }
  }
  else
  {
    cutoff = new DateTime(reference.Year, birth.Month, birth.Day);
  }

  int age = (reference.Year - birth.Year) + (reference >= cutoff ? 0 : -1);
  return age < 0 ? 0 : age;
}

ควรสังเกตว่ารหัสนี้ถือว่า:

  • การคำนวณอายุตะวันตกและยุโรป
  • ปฏิทินเช่นปฏิทินแบบคริสต์ศักราชที่แทรกวันกระโดดครั้งเดียวในตอนท้ายของเดือน

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

ฉันไม่แน่ใจว่าคุณต้องการให้มันกลับมาอย่างไรดังนั้นฉันเพิ่งสร้างสตริงที่อ่านได้


18

นี่ไม่ใช่คำตอบโดยตรง แต่มีเหตุผลเชิงปรัชญามากกว่าเกี่ยวกับปัญหาที่เกิดขึ้นจากมุมมองเสมือนวิทยาศาสตร์

ฉันจะโต้แย้งว่าคำถามไม่ได้ระบุหน่วยหรือวัฒนธรรมที่จะวัดอายุคำตอบส่วนใหญ่ดูเหมือนจะถือว่าเป็นตัวแทนประจำปีจำนวนเต็ม SI-unit สำหรับเวลาคือsecondคำตอบทั่วไปที่ถูกต้องควรเป็น (แน่นอนว่าสมมติว่าเป็นมาตรฐานDateTimeและไม่คำนึงถึงผลกระทบเชิงสัมพัทธภาพใด ๆ ):

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

ในแบบของคริสเตียนในการคำนวณอายุในปี:

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

ในทางการเงินมีปัญหาที่คล้ายกันเมื่อคำนวณบางสิ่งบางอย่างที่เรียกว่าเศษส่วนการนับวันซึ่งประมาณเป็นจำนวนปีสำหรับระยะเวลาที่กำหนด และปัญหาเรื่องอายุเป็นเรื่องของการวัดเวลา

ตัวอย่างสำหรับการประชุมจริง / จริง (นับวัน "ถูกต้อง") ทั้งหมด:

DateTime start, end = .... // Whatever, assume start is before end

double startYearContribution = 1 - (double) start.DayOfYear / (double) (DateTime.IsLeapYear(start.Year) ? 366 : 365);
double endYearContribution = (double)end.DayOfYear / (double)(DateTime.IsLeapYear(end.Year) ? 366 : 365);
double middleContribution = (double) (end.Year - start.Year - 1);

double DCF = startYearContribution + endYearContribution + middleContribution;

อีกวิธีที่ใช้กันทั่วไปในการวัดเวลาโดยทั่วไปคือ "ซีเรียลไลซ์เซชั่น" (เพื่อนที่ตั้งชื่อการประชุมวันที่นี้อย่างจริงจังจะต้องเป็น trippin '):

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

ฉันสงสัยว่าเราต้องไปนานแค่ไหนก่อนอายุความสัมพันธ์ในไม่กี่วินาทีจะมีประโยชน์มากกว่าการประมาณคร่าวๆของวัฏจักรโลกรอบดวงอาทิตย์ในช่วงชีวิตของเราจนถึงตอนนี้ :) หรือกล่าวอีกนัยหนึ่งเมื่อต้องกำหนดสถานที่หรือ ฟังก์ชั่นที่เป็นตัวแทนของการเคลื่อนไหวสำหรับตัวเองจะถูกต้อง :)


17

นี่คือทางออก

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

ด้วยสตริง concat จะเป็นไปได้: 47 ปี 11 Mo 7 วัน
JoshYates1980

16

นี่เป็นหนึ่งในคำตอบที่แม่นยำที่สุดที่สามารถแก้ไขวันเกิดวันที่ 29 กุมภาพันธ์เมื่อเทียบกับปีที่ 28 กุมภาพันธ์ใด ๆ

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

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

    return age;
}




มันเป็นวันนี้! (อันถัดไปคือสี่ปีต่อจากนี้)
Peter Mortensen

15

ฉันมีวิธีการที่กำหนดเองเพื่อคำนวณอายุพร้อมข้อความยืนยันการตรวจสอบโบนัสในกรณีที่มันช่วย:

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
}

วิธีการเรียกที่นี่และส่งออกค่าวันที่และเวลา (MM / dd / yyyy ถ้าเซิร์ฟเวอร์ตั้งค่าเป็นสถานที่เกิดเหตุสหรัฐอเมริกา) แทนที่สิ่งนี้ด้วยกล่องข้อความหรือภาชนะใด ๆ ที่จะแสดง:

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

จำไว้ว่าคุณสามารถจัดรูปแบบข้อความได้ตามที่คุณต้องการ


14

วิธีการแก้ปัญหานี้?

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

วิธีการดังต่อไปนี้ (แยกจากห้องสมุดระยะเวลาสำหรับ. NET class DateDiff ) พิจารณาปฏิทินของข้อมูลวัฒนธรรม:

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

การใช้งาน:

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

คำถามคลาสสิคนี้สมควรได้รับโซลูชัน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;
}

การใช้งาน:

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

คุณอาจสนใจในการปรับปรุงต่อไปนี้:

  • การส่งผ่านนาฬิกาเป็นการใช้IClockแทนSystemClock.Instanceจะช่วยเพิ่มความสามารถในการทดสอบ

  • เขตเวลาเป้าหมายมีแนวโน้มที่จะเปลี่ยนแปลงดังนั้นคุณจึงต้องการDateTimeZoneพารามิเตอร์เช่นกัน

ดูโพสต์บล็อกของฉันในเรื่องนี้: การจัดการวันเกิดและวันครบรอบอื่น ๆ


คุณเข้าร่วมกับ Noda Time หรือไม่?
Zimano

ฉันได้ให้การสนับสนุน แต่เป็นหลักของ Jon Skeet
Matt Johnson-Pint

9

ฉันใช้โซลูชันของ ScArcher2 สำหรับการคำนวณปีที่ถูกต้องของอายุบุคคล แต่ฉันต้องดำเนินการเพิ่มเติมและคำนวณเดือนและวันพร้อมกับปี

    public static Dictionary<string,int> CurrentAgeInYearsMonthsDays(DateTime? ndtBirthDate, DateTime? ndtReferralDate)
    {
        //----------------------------------------------------------------------
        // Can't determine age if we don't have a dates.
        //----------------------------------------------------------------------
        if (ndtBirthDate == null) return null;
        if (ndtReferralDate == null) return null;

        DateTime dtBirthDate = Convert.ToDateTime(ndtBirthDate);
        DateTime dtReferralDate = Convert.ToDateTime(ndtReferralDate);

        //----------------------------------------------------------------------
        // Create our Variables
        //----------------------------------------------------------------------
        Dictionary<string, int> dYMD = new Dictionary<string,int>();
        int iNowDate, iBirthDate, iYears, iMonths, iDays;
        string sDif = "";

        //----------------------------------------------------------------------
        // Store off current date/time and DOB into local variables
        //---------------------------------------------------------------------- 
        iNowDate = int.Parse(dtReferralDate.ToString("yyyyMMdd"));
        iBirthDate = int.Parse(dtBirthDate.ToString("yyyyMMdd"));

        //----------------------------------------------------------------------
        // Calculate Years
        //----------------------------------------------------------------------
        sDif = (iNowDate - iBirthDate).ToString();
        iYears = int.Parse(sDif.Substring(0, sDif.Length - 4));

        //----------------------------------------------------------------------
        // Store Years in Return Value
        //----------------------------------------------------------------------
        dYMD.Add("Years", iYears);

        //----------------------------------------------------------------------
        // Calculate Months
        //----------------------------------------------------------------------
        if (dtBirthDate.Month > dtReferralDate.Month)
            iMonths = 12 - dtBirthDate.Month + dtReferralDate.Month - 1;
        else
            iMonths = dtBirthDate.Month - dtReferralDate.Month;

        //----------------------------------------------------------------------
        // Store Months in Return Value
        //----------------------------------------------------------------------
        dYMD.Add("Months", iMonths);

        //----------------------------------------------------------------------
        // Calculate Remaining Days
        //----------------------------------------------------------------------
        if (dtBirthDate.Day > dtReferralDate.Day)
            //Logic: Figure out the days in month previous to the current month, or the admitted month.
            //       Subtract the birthday from the total days which will give us how many days the person has lived since their birthdate day the previous month.
            //       then take the referral date and simply add the number of days the person has lived this month.

            //If referral date is january, we need to go back to the following year's December to get the days in that month.
            if (dtReferralDate.Month == 1)
                iDays = DateTime.DaysInMonth(dtReferralDate.Year - 1, 12) - dtBirthDate.Day + dtReferralDate.Day;       
            else
                iDays = DateTime.DaysInMonth(dtReferralDate.Year, dtReferralDate.Month - 1) - dtBirthDate.Day + dtReferralDate.Day;       
        else
            iDays = dtReferralDate.Day - dtBirthDate.Day;             

        //----------------------------------------------------------------------
        // Store Days in Return Value
        //----------------------------------------------------------------------
        dYMD.Add("Days", iDays);

        return dYMD;
}

9

เวอร์ชัน 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

ฉันได้ทำการเปลี่ยนแปลงเล็กน้อยในคำตอบของ Mark Soen : ฉันเขียนบรรทัดที่สามขึ้นมาใหม่เพื่อให้สามารถแยกวิเคราะห์นิพจน์ได้ง่ายขึ้น

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

ฉันยังทำให้มันเป็นฟังก์ชั่นเพื่อความชัดเจน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.