Age Calculator in C++: Calculate Age from Date of Birth
10 min read

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

If you need an age calculator in C++, the safest modern approach is to treat age as a calendar calculation rather than subtracting two years or dividing elapsed seconds by a fixed number. In C++20, the <chrono> calendar types give you std::chrono::year_month_day, date validation with ok(), and conversions to day-based time points.

This guide builds a reusable C++20 age calculator from a date of birth (DOB). It covers completed age, age on a fixed date, exact years-months-days, total elapsed days, input validation, leap years, February 29 birthdays, testing, and common implementation mistakes.

C++ logo for an age calculator in C++ tutorial
Source: Wikimedia Commons, Adrien Memel; CC BY-SA 4.0.

Quick answer: C++ age calculator from DOB

For a completed-age calculation, compare the birthday month and day with the month and day of the reference date. If the birthday has not occurred yet in the reference year, subtract one from the year difference.

#include <chrono>

int completed_age(std::chrono::year_month_day dob,
                  std::chrono::year_month_day as_of)
{
    int age = int(as_of.year()) - int(dob.year());

    const auto birthday_this_year =
        std::chrono::year_month_day{as_of.year(), dob.month(), dob.day()};

    if (as_of.month() < dob.month() ||
        (as_of.month() == dob.month() && as_of.day() < dob.day())) {
        --age;
    }

    return age;
}

The example assumes a valid, non-February-29 birthday. A production calculator should explicitly choose a policy for February 29, discussed below.

Why simple year subtraction is not enough

Suppose a person was born on 15 November 2000 and the reference date is 10 September 2026. The raw year difference is 26, but the 2026 birthday has not happened yet, so the completed age is 25.

DOBAs-of dateYear differenceCompleted age
15 Nov 200010 Sep 20262625
15 Nov 200015 Nov 20262626
15 Nov 200020 Dec 20262626

This birthday check is the key distinction between a calendar age and a rough duration calculation.

Use C++20 chrono calendar types

C++20 added calendar facilities to std::chrono. The year_month_day type represents a specific calendar date, supports year- and month-oriented arithmetic, and can be converted to sys_days for day-based arithmetic. Its ok() member can be used to validate whether the stored year, month, and day form a valid date.

For an age calculator, this is preferable to manually storing dates as three unrelated integers and implementing month lengths from scratch.

Build a completed-age function

#include <chrono>

using namespace std::chrono;

int completed_age(year_month_day dob, year_month_day as_of)
{
    int age = int(as_of.year()) - int(dob.year());

    if (as_of.month() < dob.month() ||
        (as_of.month() == dob.month() && as_of.day() < dob.day())) {
        --age;
    }

    return age;
}

Before calling this function, validate both dates and make sure the DOB is not after the reference date. A negative result is normally an input error, not a meaningful age.

Validate a date of birth

#include <chrono>

bool valid_dob(std::chrono::year_month_day dob,
               std::chrono::year_month_day as_of)
{
    return dob.ok() && as_of.ok() &&
           std::chrono::sys_days{dob} <= std::chrono::sys_days{as_of};
}

ok() catches invalid calendar combinations such as 31 April. Comparing the corresponding sys_days values then lets you reject a DOB that lies in the future relative to the chosen as-of date.

Calculate age on a fixed date

A fixed reference date makes an age calculator deterministic. It is useful for eligibility checks, historical records, tests, and forms where the rule says age must be measured on a particular cutoff date.

#include <chrono>
#include <iostream>

int main()
{
    using namespace std::chrono;

    const year_month_day dob{2000y, November, 15d};
    const year_month_day cutoff{2026y, September, 10d};

    if (!dob.ok() || !cutoff.ok() ||
        sys_days{dob} > sys_days{cutoff}) {
        std::cerr << "Invalid dates\n";
        return 1;
    }

    std::cout << completed_age(dob, cutoff) << '\n';
}

Calculate years, months, and days

Completed years are often enough, but an age calculator may also need an exact calendar interval such as 25 years, 9 months, 26 days. C++20’s calendar types provide the building blocks, but there is no single standard-library function named “age difference” that directly returns that three-part human age interval. A practical approach is to advance the DOB by completed years, then completed months, and finally count remaining days.

#include <chrono>

struct AgeParts {
    int years;
    int months;
    int days;
};

AgeParts age_parts(std::chrono::year_month_day dob,
                   std::chrono::year_month_day as_of)
{
    using namespace std::chrono;

    int years = int(as_of.year()) - int(dob.year());
    auto anniversary = dob + years{years};

    if (anniversary > as_of) {
        --years;
        anniversary = dob + years{years};
    }

    int months = (int(as_of.year()) - int(anniversary.year())) * 12
               + (int(as_of.month()) - int(anniversary.month()));

    auto month_mark = anniversary + months{months};

    if (month_mark > as_of) {
        --months;
        month_mark = anniversary + months{months};
    }

    const auto days = duration_cast<days>(
        sys_days{as_of} - sys_days{month_mark}
    ).count();

    return {years, months, static_cast<int>(days)};
}

For business-critical applications, test this routine against the exact rules your domain uses, especially around month-end dates and February 29.

Calculate total elapsed days

If the requirement is the number of calendar days between DOB and a reference date, convert both valid year_month_day values to sys_days and subtract them.

#include <chrono>

long long elapsed_days(std::chrono::year_month_day dob,
                       std::chrono::year_month_day as_of)
{
    using namespace std::chrono;

    return duration_cast<days>(
        sys_days{as_of} - sys_days{dob}
    ).count();
}

This gives an elapsed-day count, not a person’s completed age in years. Those are different measurements and should not be substituted for one another.

Parse and construct dates safely

For a controlled application, constructing dates from numeric components is straightforward. C++20 also provides chrono parsing facilities. If you accept user input, validate the parsed result with ok() and reject malformed or impossible dates before calculating age.

#include <chrono>
#include <iostream>
#include <sstream>
#include <stdexcept>

std::chrono::year_month_day parse_date(const std::string& text)
{
    std::istringstream input{text};
    std::chrono::year_month_day date;
    input >> std::chrono::parse("%F", date);

    if (!input || !date.ok()) {
        throw std::invalid_argument("Invalid date");
    }

    return date;
}

The exact parsing support and compiler library version matter, so verify your target C++20 standard-library implementation when deploying this code.

What about today’s date?

If the calculator should use the current date, obtain a day-level value from the system clock and convert it to year_month_day. Keeping the reference date explicit makes the core age function easier to test.

#include <chrono>

auto today()
{
    using namespace std::chrono;

    return year_month_day{
        floor<days>(system_clock::now())
    };
}

For applications that care about a user’s local calendar day, consider the application’s time-zone requirements rather than assuming the server’s clock is the user’s local date.

Handle February 29 birthdays explicitly

A person born on February 29 has a birthday that does not appear in most years. There is no universal rule for whether a non-leap-year birthday should be treated as February 28, March 1, or another legally defined date. The calculator should therefore document its policy instead of silently choosing one.

PolicyNon-leap-year treatmentUse when
Feb 28Birthday is observed on Feb 28A domain explicitly defines this rule
Mar 1Birthday is observed on Mar 1A domain explicitly defines this rule
Custom/legal ruleUse the applicable jurisdiction or policyEligibility or legal calculations

Common mistakes in C++ age calculators

MistakeWhy it failsBetter approach
Subtracting years onlyIgnores whether the birthday occurredCompare month and day
Dividing seconds by 365 daysIgnores leap days and calendar boundariesUse calendar dates for age
Accepting 31 AprilCreates an impossible dateCheck year_month_day::ok()
Allowing a future DOBProduces a negative or invalid ageCompare DOB with as-of date
Ignoring Feb 29Creates ambiguous birthday behaviorDocument an explicit policy

Testing an age calculator in C++

Age calculations should be tested at calendar boundaries, not just with ordinary dates. Include cases immediately before and on a birthday, leap-day dates, month ends, and invalid input.

Test caseExpected behavior
DOB is exactly the as-of dateAge is 0
As-of date is one day before birthdayAge is one less than the raw year difference
As-of date is birthdayAge increments
Leap-year DOB of Feb 29Configured Feb 29 policy is applied
Future DOBReject input
Invalid date such as Apr 31Reject input

Minimal complete C++20 example

#include <chrono>
#include <iostream>
#include <stdexcept>

int completed_age(std::chrono::year_month_day dob,
                  std::chrono::year_month_day as_of)
{
    if (!dob.ok() || !as_of.ok() ||
        std::chrono::sys_days{dob} > std::chrono::sys_days{as_of}) {
        throw std::invalid_argument("Invalid age-calculation dates");
    }

    int age = int(as_of.year()) - int(dob.year());

    if (as_of.month() < dob.month() ||
        (as_of.month() == dob.month() && as_of.day() < dob.day())) {
        --age;
    }

    return age;
}

int main()
{
    using namespace std::chrono;

    const year_month_day dob{2000y, November, 15d};
    const year_month_day as_of{2026y, September, 10d};

    std::cout << "Age: "
              << completed_age(dob, as_of)
              << '\n';
}

Compile this as C++20 or later because the calendar types used here are C++20 facilities.

C++ age calculator vs elapsed-time calculation

RequirementRecommended representation
Completed ageyear_month_day with birthday comparison
Exact years-months-daysCalendar arithmetic plus remaining day count
Total dayssys_days subtraction
Validationyear_month_day::ok() plus chronological comparison
Current datesystem_clock converted to day precision

Frequently asked questions

Can I calculate age in C++ without C++20?

Yes. Older C++ versions can use the C time API or a date library, but the calendar types used in this tutorial are from C++20. If your project is restricted to C++11, C++14, or C++17, the implementation needs a different date representation.

Is C++ age calculation just the current year minus birth year?

No. The birthday must be checked. If the birthday has not occurred in the reference year, the completed age is one less than the raw year difference.

How do I calculate age on a particular date?

Pass the required cutoff date as the as_of argument instead of reading today’s date inside the calculation. This makes the result reproducible and easier to test.

How do I calculate total days from DOB in C++?

Convert both valid dates to std::chrono::sys_days and subtract them. The resulting duration can be converted to days. Do not convert that number directly into calendar age.

Does C++20 handle leap years?

The C++20 chrono calendar types model calendar dates and provide date validation, including whether a constructed date is valid. Your application still needs an explicit business rule for how a February 29 birthday is observed in non-leap years.

Related age-calculator programming guides

Sources and technical references

Takeaway: a reliable age calculator in C++ should calculate completed years from calendar dates, validate the DOB, keep the reference date explicit, and treat leap-day birthdays as a documented business rule. C++20’s std::chrono calendar facilities provide a strong foundation for these calculations.