Age Calculator in C#: Calculate Age from Date of Birth
8 min read

Age Calculator in C#: Calculate Age from Date of Birth

Building an age calculator in C# is straightforward once you treat age as a calendar calculation rather than a simple subtraction of years. This guide shows how to calculate completed age from a date of birth, calculate age on a fixed date, return years-months-days, validate future dates, and calculate elapsed days with modern .NET date types.

C# logo for an age calculator in C# tutorial
Source: Wikimedia Commons, Microsoft; CC0.

Quick answer: completed age in C#

For a date-only age calculator on .NET 6 and later, DateOnly is a natural fit because a birthday has a date but no time-of-day component. Microsoft documents DateOnly as a type for representing a specific date without a time, and specifically notes that it is useful for dates such as birth dates. Microsoft Learn: DateOnly and TimeOnly

using System;

static int CalculateAge(DateOnly birthDate, DateOnly asOfDate)
{
    if (birthDate > asOfDate)
        throw new ArgumentException("Birth date cannot be after the calculation date.");

    int age = asOfDate.Year - birthDate.Year;

    if (birthDate.AddYears(age) > asOfDate)
        age--;

    return age;
}

var birthDate = new DateOnly(1995, 9, 21);
var today = DateOnly.FromDateTime(DateTime.Today);

Console.WriteLine(CalculateAge(birthDate, today));

The key check is birthDate.AddYears(age) > asOfDate. It prevents the calculator from counting the current calendar year before the birthday has actually occurred.

Why subtracting the years is not enough

A tempting implementation is asOfDate.Year - birthDate.Year. That gives the right result only when the birthday has already occurred in the calculation year. For example, someone born on December 10, 2000 is not yet 26 on September 21, 2026; the raw year difference is 26, while the completed age is 25.

Birth dateAs-of dateYear differenceCompleted age
10 Dec 200021 Sep 20262625
10 Sep 200021 Sep 20262626
21 Sep 200021 Sep 20262626

DateOnly versus DateTime in an age calculator

DateOnly was introduced with .NET 6 and represents a date without a time. Microsoft notes that this can avoid unnecessary time-zone and time-of-day concerns when the value is inherently a calendar date. It is therefore a good match for a birth date and an as-of date in a conventional age calculator. Microsoft Learn: choosing between DateTime and DateOnly

TypeUse in an age calculatorTypical concern
DateOnlyBirth date and calendar as-of dateRequires .NET 6+
DateTimeOlder applications or date-time APIsTime and time-zone semantics can be unnecessary
DateTimeOffsetWhen a real instant in time mattersUsually more detail than a birthday calculation needs

Age on a fixed date

An age calculator should usually accept an explicit as-of date rather than always using the machine’s current date. That makes the function deterministic, easier to test, and useful for eligibility or historical calculations.

var birthDate = new DateOnly(1988, 4, 15);
var asOfDate = new DateOnly(2026, 9, 21);

int age = CalculateAge(birthDate, asOfDate);

Console.WriteLine($"Age on {asOfDate:dd MMM yyyy}: {age}");

Calculate years, months, and days

If your UI needs an exact calendar-style result such as “31 years, 4 months, 6 days,” calculate the completed years first, then advance from the anniversary by whole months, and finally count the remaining calendar days. DateOnly.DayNumber provides a convenient integer representation for the day difference. Microsoft documents DayNumber as the number of days since January 1, 0001 in the proleptic Gregorian calendar. Microsoft Learn: DateOnly

static (int Years, int Months, int Days) CalculateAgeYmd(
    DateOnly birthDate,
    DateOnly asOfDate)
{
    if (birthDate > asOfDate)
        throw new ArgumentException("Birth date cannot be after the calculation date.");

    int years = asOfDate.Year - birthDate.Year;
    DateOnly anniversary = birthDate.AddYears(years);

    if (anniversary > asOfDate)
    {
        years--;
        anniversary = birthDate.AddYears(years);
    }

    int months = 0;
    DateOnly cursor = anniversary;

    while (cursor.AddMonths(1) <= asOfDate)
    {
        cursor = cursor.AddMonths(1);
        months++;
    }

    int days = asOfDate.DayNumber - cursor.DayNumber;

    return (years, months, days);
}

var result = CalculateAgeYmd(
    new DateOnly(1990, 5, 17),
    new DateOnly(2026, 9, 21));

Console.WriteLine($"{result.Years} years, {result.Months} months, {result.Days} days");

This approach keeps the units calendar-aware: years are completed birthdays, months are completed calendar months after the last anniversary, and the final value is the remaining number of days.

Calculate total elapsed days

Sometimes “age” means the total number of days elapsed rather than completed years. With DateOnly, subtracting the two DayNumber values gives a direct day count.

static int TotalDays(DateOnly birthDate, DateOnly asOfDate)
{
    if (birthDate > asOfDate)
        throw new ArgumentException("Birth date cannot be after the calculation date.");

    return asOfDate.DayNumber - birthDate.DayNumber;
}

Validate a date of birth

Never silently accept a future birth date. If the value comes from a web form, API, database, or user input, parse and validate it before running the calculation.

if (!DateOnly.TryParse(input, out DateOnly birthDate))
{
    Console.WriteLine("Enter a valid date.");
    return;
}

DateOnly asOfDate = DateOnly.FromDateTime(DateTime.Today);

if (birthDate > asOfDate)
{
    Console.WriteLine("Birth date cannot be in the future.");
    return;
}

Console.WriteLine(CalculateAge(birthDate, asOfDate));

A complete C# console example

using System;

static int CalculateAge(DateOnly birthDate, DateOnly asOfDate)
{
    if (birthDate > asOfDate)
        throw new ArgumentException("Birth date cannot be after the calculation date.");

    int age = asOfDate.Year - birthDate.Year;

    if (birthDate.AddYears(age) > asOfDate)
        age--;

    return age;
}

Console.Write("Enter date of birth (yyyy-MM-dd): ");
string? input = Console.ReadLine();

if (!DateOnly.TryParse(input, out DateOnly birthDate))
{
    Console.WriteLine("Invalid date.");
    return;
}

DateOnly today = DateOnly.FromDateTime(DateTime.Today);

if (birthDate > today)
{
    Console.WriteLine("Birth date cannot be in the future.");
    return;
}

int age = CalculateAge(birthDate, today);

Console.WriteLine($"Completed age: {age} years");
Console.WriteLine($"Total elapsed days: {today.DayNumber - birthDate.DayNumber}");

Leap years and February 29 birthdays

February 29 needs an explicit business rule when the target year is not a leap year. The sample above relies on .NET’s calendar behavior when AddYears produces a date whose day is invalid in the target year: the resulting day is adjusted to the last valid day of that month. Microsoft documents this adjustment behavior for calendar year addition. Microsoft Learn: Calendar.AddYears

CaseWhat to decide
Feb 29 DOB, non-leap as-of yearWhether the birthday is treated as Feb 28 or another local/business rule
Feb 29 DOB, leap as-of yearThe calendar date exists, so the normal anniversary comparison applies
Eligibility ruleFollow the specific policy if a law, employer, exam, or application defines a different cutoff rule

Testing an age calculator in C#

Test dates around the birthday rather than testing only obvious mid-year examples. Fixed as-of dates make the tests repeatable.

TestExpected behavior
DOB equals as-of date0 years
One day before birthdayPrevious completed age
Birthday itselfNew completed age
DOB in the futureValidation error
Feb 29 DOBMatches the application’s documented birthday policy
Very old valid DOBNo integer or calendar arithmetic shortcut should produce an incorrect result

Common mistakes

  • Subtracting years only: this can overstate age before the birthday.
  • Dividing elapsed days by 365: leap years make that unsuitable for completed calendar age.
  • Ignoring future dates: a future DOB should be rejected unless the application has a special reason to allow it.
  • Mixing time zones into a date-only problem: use DateOnly when the input is fundamentally a calendar date.
  • Leaving Feb 29 undefined: document the policy your application follows.
  • Using today’s date inside every function: accepting an as-of date makes the calculation easier to test and reuse.

C# age calculator: DateOnly versus DateTime

RequirementRecommended approach
Birthday and calendar ageDateOnly on .NET 6+
Legacy .NET Framework projectDateTime with the time portion normalized or ignored carefully
Exact instant across time zonesDateTimeOffset may be more appropriate
Age on a historical datePass an explicit DateOnly asOfDate

Frequently asked questions

How do I calculate age from DOB in C#?

Subtract the birth year from the as-of year, then reduce the result by one when the birthday anniversary in that year is later than the as-of date. The DateOnly.AddYears approach shown above keeps that comparison calendar-aware.

Can I use DateTime instead of DateOnly?

Yes. DateTime is still useful for applications that target older frameworks or APIs that require it. For a pure birthday calculation, however, DateOnly communicates that the time of day is not part of the data.

How do I calculate age as of a particular date in C#?

Pass the desired date as the second argument to the age function instead of reading the current date inside the function. This lets the same calculation work for today’s age, a historical date, or a future eligibility cutoff.

Does C# handle leap years?

Yes. The .NET date types implement calendar rules, but your application still needs a clear policy for interpreting a February 29 birthday in a non-leap year when that distinction matters.

Related age calculator tutorials

If you are implementing the same calculation in another language or stack, see our guides to the age calculator in JavaScript, age calculator in Java, age calculator in Python, and age calculator in SQL.

Sources

Bottom line: For a modern .NET application, use DateOnly for birth dates, compare the birthday anniversary against the as-of date, validate future DOBs, and make any February 29 policy explicit. That produces an age calculator in C# that is easier to test and less prone to off-by-one errors.