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

Age Calculator in Dart: Calculate Age from Date of Birth

If you need an age calculator in Dart, the safest approach is to treat age as a calendar calculation rather than simply dividing a duration by 365. Dart’s DateTime class gives you the year, month and day components you need to determine whether the birthday has occurred in the reference year. This approach also lets you calculate age on a fixed date, return years-months-days, validate future dates of birth, and calculate elapsed days when that is the actual requirement.

Quick answer: for completed age, calculate asOf.year - dob.year, then subtract one when the birthday has not occurred yet in the reference year. For calendar-date input, prefer an explicit date representation such as a UTC DateTime at midnight so daylight-saving clock changes do not affect whole-day calculations.

Dart logo for an age calculator in Dart tutorial
Source: Wikimedia Commons, Google; CC BY 4.0.

Age Calculator in Dart: What You Should Calculate

An age calculator can mean several different things. Before writing the Dart function, decide whether the output is:

  • Completed age: whole birthdays already reached.
  • Age on a fixed date: completed age on a supplied as-of date rather than today.
  • Calendar age: years, months and days since the date of birth.
  • Elapsed days: the number of whole calendar-day intervals between two dates.

These definitions are not interchangeable. Dart’s DateTime.difference() returns a Duration measured from the underlying time values, so it is useful for elapsed time but should not be used as the sole definition of completed birthday age. The Dart API also warns that local-time differences across daylight-saving changes can make a pair of local midnights less than 24 hours apart. Dart DateTime documentation

Dart DateTime Basics for Age Calculations

Dart’s DateTime represents an instant in either UTC or the local time zone. Its year, month and day properties expose the calendar components needed for birthday logic. The DateTime.utc() constructor is particularly useful when you want date values that are not affected by daylight-saving transitions. Dart DateTime API

final dob = DateTime.utc(1995, 7, 14);
final asOf = DateTime.utc(2026, 9, 22);

print(dob.year);  // 1995
print(dob.month); // 7
print(dob.day);   // 14

Calculate Completed Age in Dart

The standard birthday-aware rule is simple: start with the difference between the reference year and birth year. If the reference month/day comes before the birthday in that year, subtract one.

int calculateAge(DateTime dob, DateTime asOf) {
  if (dob.isAfter(asOf)) {
    throw ArgumentError('Date of birth cannot be in the future.');
  }

  int age = asOf.year - dob.year;

  final birthdayThisYear = DateTime.utc(
    asOf.year,
    dob.month,
    dob.day,
  );

  if (birthdayThisYear.isAfter(asOf)) {
    age--;
  }

  return age;
}

This works because a person whose birthday has not arrived yet in the reference year has completed one fewer year. The function also accepts an explicit asOf date, which makes it deterministic for tests and historical calculations.

Date of birthAs-of dateCompleted age
14 July 199522 September 202631
14 October 199522 September 202630
22 September 199522 September 202631

Why Subtracting Years Alone Can Be Wrong

A formula such as asOf.year - dob.year ignores whether the birthday has happened. For example, someone born on 14 October 1995 is still 30 on 22 September 2026, not 31. The month-and-day comparison is therefore essential.

Likewise, dividing the result of difference() by 365 or 365.25 is not a reliable definition of completed age. Leap years change the number of elapsed days, and a birthday is a calendar event rather than a fixed number of seconds.

Calculate Age on a Fixed Date

A production age calculator should normally accept an explicit reference date. That makes the same function useful for eligibility cutoffs, historical records, reports and unit tests.

final dob = DateTime.utc(2000, 2, 29);
final cutoff = DateTime.utc(2026, 2, 28);

final age = calculateAge(dob, cutoff);
print(age);

Whether a person born on February 29 has a birthday on February 28 or March 1 in a non-leap year is a policy question. Your application should document the rule instead of silently assuming one. A jurisdiction, contract or eligibility notice may define its own cutoff convention.

Calculate Years, Months and Days in Dart

Dart’s core DateTime API does not provide a direct Period-style calendar interval with normalized years, months and days. You can build the result by first calculating completed years, then advancing the birth date by that many years and breaking the remaining interval into months and days.

class AgeResult {
  final int years;
  final int months;
  final int days;

  const AgeResult(this.years, this.months, this.days);
}

AgeResult calculateYmdAge(DateTime dob, DateTime asOf) {
  if (dob.isAfter(asOf)) {
    throw ArgumentError('Date of birth cannot be in the future.');
  }

  var years = asOf.year - dob.year;
  var anniversary = DateTime.utc(
    dob.year + years,
    dob.month,
    dob.day,
  );

  if (anniversary.isAfter(asOf)) {
    years--;
    anniversary = DateTime.utc(
      dob.year + years,
      dob.month,
      dob.day,
    );
  }

  var months = 0;
  var cursor = anniversary;

  while (true) {
    final next = DateTime.utc(cursor.year, cursor.month + 1, cursor.day);
    if (next.isAfter(asOf)) {
      break;
    }
    cursor = next;
    months++;
  }

  final days = asOf.difference(cursor).inDays;
  return AgeResult(years, months, days);
}

Month-end dates need extra care because Dart normalizes out-of-range date components. For a robust application, test dates such as January 31, February 28/29 and months with 30 days. If your requirements are internationalized or depend heavily on calendar conventions, consider whether the Dart intl package or a dedicated date library is more appropriate than hand-written month arithmetic.

Calculate Total Elapsed Days

When the requirement really is elapsed days, use difference(). For date-only calculations, using UTC midnight values avoids daylight-saving transitions changing the duration between two local midnights.

int elapsedDays(DateTime start, DateTime end) {
  if (end.isBefore(start)) {
    throw ArgumentError('End date must not be before start date.');
  }

  return end.difference(start).inDays;
}

final start = DateTime.utc(2000, 1, 1);
final end = DateTime.utc(2026, 9, 22);

print(elapsedDays(start, end));

Dart’s documentation specifically notes that Duration.inDays reports whole days and that local-time calculations can be affected by daylight-saving changes. For date-only age calculations, UTC values are therefore a useful defensive choice. Dart difference() documentation

Parse a Date of Birth Safely

DateTime.parse() accepts a subset of ISO 8601 and throws a FormatException for strings it cannot parse. Importantly, the parser can normalize some out-of-range component values rather than rejecting every invalid calendar date. For strict user input, validate the original components or use an appropriate strict date parser instead of assuming that successful parsing means the user entered a valid calendar date. Dart DateTime.parse documentation

DateTime? parseDob(String input) {
  try {
    final parsed = DateTime.parse(input);
    return DateTime.utc(parsed.year, parsed.month, parsed.day);
  } on FormatException {
    return null;
  }
}

For a browser or Flutter form, it is also a good idea to reject blank values, future dates and values outside the date range your application supports before calculating age.

Complete Dart Age Calculator Example

int calculateAge(DateTime dob, DateTime asOf) {
  if (dob.isAfter(asOf)) {
    throw ArgumentError('Date of birth cannot be in the future.');
  }

  var age = asOf.year - dob.year;

  final birthday = DateTime.utc(
    asOf.year,
    dob.month,
    dob.day,
  );

  if (birthday.isAfter(asOf)) {
    age--;
  }

  return age;
}

void main() {
  final dob = DateTime.utc(1990, 11, 5);
  final today = DateTime.utc(2026, 9, 22);

  final age = calculateAge(dob, today);

  print('Age: $age years');
}

The important part is not the print() statement; it is the separation between date parsing, validation, the as-of date and the age rule. Keeping those responsibilities separate makes the calculator easier to test and reuse in command-line, server-side or Flutter applications.

Leap Years and February 29

Leap-day birthdays deserve an explicit test. If the birth date is February 29, the birthday comparison for a non-leap reference year needs a documented business rule. Do not assume that every application should treat February 28 and March 1 identically.

Test caseWhat to verify
29 Feb in a leap yearBirthday is a real calendar date.
29 Feb to a non-leap yearApplication’s birthday policy is explicit.
Birthday todayAge increases on the birthday.
Birthday tomorrowAge remains one year lower.

Time Zones: DateTime.now() vs UTC

DateTime.now() returns the current date and time in the computer’s local time zone. That may be exactly what a local application needs, but a server that serves users in several time zones should define which calendar date is authoritative. For date-only records such as birthdays, converting user input into a consistent date representation can prevent an age from changing unexpectedly around midnight.

Dart’s DateTime.utc() constructor creates UTC values, and the official API recommends UTC for historic or date-oriented calculations where daylight-saving changes should not affect the result. Dart UTC DateTime documentation

Testing a Dart Age Calculator

Use fixed dates in tests instead of relying on DateTime.now(). That makes the expected answer stable and lets you cover boundary cases.

ScenarioExpected behavior
DOB before birthdaySubtract one from the raw year difference.
DOB on birthdayUse the raw year difference.
Future DOBReject the input.
29 February DOBApply the documented non-leap-year policy.
Month-end DOBVerify years-months-days normalization.
Different time zonesConfirm the application’s authoritative calendar date.
void main() {
  final asOf = DateTime.utc(2026, 9, 22);

  assert(
    calculateAge(DateTime.utc(1995, 9, 22), asOf) == 31,
  );

  assert(
    calculateAge(DateTime.utc(1995, 10, 14), asOf) == 30,
  );
}

Common Mistakes in a Dart Age Calculator

  • Using only asOf.year - dob.year and ignoring the birthday.
  • Dividing elapsed days by 365 and calling the result a completed age.
  • Using local midnight durations without considering daylight-saving changes.
  • Accepting a future date of birth.
  • Assuming DateTime.parse() rejects every out-of-range calendar component.
  • Leaving the February 29 rule undocumented.
  • Using DateTime.now() directly in tests, which makes results change over time.

Dart DateTime vs Other Age-Calculator Implementations

ImplementationCore date approachUseful when
DartDateTimeFlutter, Dart CLI and Dart server applications.
JavaScriptDate / calendar logicBrowser-based calculators.
TypeScriptTyped DateTyped JavaScript applications.
JavaLocalDate and PeriodJVM applications needing richer calendar types.
SwiftFoundation CalendarApple-platform applications.

If you are comparing implementation patterns, see our related guides on JavaScript, TypeScript, Java and Swift.

Frequently Asked Questions

How do I calculate age from DOB in Dart?

Subtract the birth year from the as-of year, then subtract one if the birthday in the as-of year has not occurred yet. Compare the month and day rather than relying only on elapsed seconds.

Can I use DateTime.difference() for age?

Use difference() for elapsed durations and elapsed days. It is not, by itself, a birthday-aware completed-age calculation because age is based on calendar birthdays.

Does Dart DateTime support UTC?

Yes. Dart provides DateTime.utc(), an isUtc property, and toUtc()/toLocal() conversions.

How should a Dart app handle February 29 birthdays?

Choose and document the business rule for non-leap years. The correct policy depends on the purpose of the calculator and any applicable rules.

Key Takeaway

A reliable age calculator in Dart separates calendar age from elapsed duration. Use DateTime year/month/day components for completed age, accept an explicit as-of date for reproducible results, use UTC values when date-only calculations should be insulated from daylight-saving changes, and test birthday boundaries, leap years, future DOBs and month-end dates. Dart’s official API documentation supports these distinctions and provides the underlying DateTime, Duration, parsing and comparison tools. Dart DateTime API

Sources