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

Age Calculator in Scala: Calculate Age from Date of Birth

Building an age calculator in Scala is a practical example of Scala’s interoperability with the Java platform. Scala can use the Java java.time API directly, so a date of birth can be represented with LocalDate, the current date can come from LocalDate.now, and a calendar difference can be represented with Period. Scala’s official documentation demonstrates Scala using Java date/time classes such as LocalDate.

Scala programming language logo for age calculator
Scala programming language logo from Wikimedia Commons; the Commons file page identifies this text logo as public domain.

This guide shows how to calculate completed age, age on a fixed date, years-months-days, elapsed days and weeks, validate dates, handle leap years, parse ISO dates, and build reusable Scala functions. It uses the modern java.time API rather than legacy date classes.

Quick Answer: Age Calculator in Scala

  • Import java.time.LocalDate and java.time.Period.
  • Represent the date of birth as a LocalDate.
  • Use LocalDate.now for today’s date or supply a fixed target date.
  • Use Period.between for a calendar years-months-days result.
  • Use ChronoUnit.DAYS when the application needs total elapsed days.
  • Reject a target date earlier than the date of birth.

Java’s LocalDate is specifically a date without a time zone, making it suitable for a birthday date. Java’s Period represents a date-based amount in years, months and days, and Period.between calculates the period between two LocalDate values.

Why Scala Uses java.time for Dates

Scala interoperates closely with Java, so Scala applications can directly use Java’s standard date/time classes. The Scala documentation demonstrates importing and using java.time.LocalDate and DateTimeFormatter, while Scala 3 documentation notes that Scala can use the classes in the Java java.time package.

Import LocalDate and Period

import java.time.LocalDate
import java.time.Period

These two types are enough for most date-only age calculations. LocalDate stores year, month and day without a time or time zone, while Period represents a calendar amount in years, months and days.

Create a Date of Birth in Scala

val dob = LocalDate.of(2000, 3, 15)

The example creates a date for 15 March 2000. LocalDate.of validates the supplied calendar fields and rejects an invalid combination such as 30 February.

Get Today’s Date

val today = LocalDate.now

For a normal age calculator, the date-only form is preferable to an exact timestamp because the result is usually based on the calendar birthday rather than the hour and second of birth.

Calculate Age in Completed Years

A calendar age can be calculated by finding the period between the date of birth and the target date and reading its year component.

def completedAge(dob: LocalDate, target: LocalDate): Int =
  require(!target.isBefore(dob), "target date is before date of birth")
  Period.between(dob, target).getYears

Period.between returns a years-months-days period. When the birthday has not yet been reached in the target year, the years component reflects that. Java documents the calculation in terms of complete months followed by remaining days and normalized years and months.

Calculate Today’s Age

def ageToday(dob: LocalDate): Int =
  completedAge(dob, LocalDate.now)

This keeps the calculation reusable: the same function can accept today’s date, a historical date, or a future reference date.

Calculate Age on a Specific Date

val dob = LocalDate.of(1995, 7, 20)
val target = LocalDate.of(2025, 1, 1)
val age = completedAge(dob, target)

Fixed-date calculations are useful for historical reports, eligibility checks, tests, and applications where a business rule specifies a particular cutoff date.

Calculate Years, Months and Days

If the application needs a detailed result such as 32 years, 4 months and 7 days, keep the complete Period rather than extracting only the years component.

def ageYmd(dob: LocalDate, target: LocalDate): Period =
  require(!target.isBefore(dob), "target date is before date of birth")
  Period.between(dob, target)
val p = ageYmd(
  LocalDate.of(1990, 11, 24),
  LocalDate.of(2026, 9, 22)
)

println(p.getYears + " years, " + p.getMonths + " months, " + p.getDays + " days")

Period is designed for date-based amounts rather than a fixed number of seconds. Its supported units are years, months and days.

Calculate Total Elapsed Days

Total elapsed days answer a different question from calendar age. Import ChronoUnit and calculate the day difference directly.

import java.time.temporal.ChronoUnit

def elapsedDays(dob: LocalDate, target: LocalDate): Long =
  require(!target.isBefore(dob), "target date is before date of birth")
  ChronoUnit.DAYS.between(dob, target)

Do not divide this number by 365 to obtain calendar age. Leap years mean that the number of days in a calendar year is not constant.

Calculate Completed Weeks

def elapsedWeeks(dob: LocalDate, target: LocalDate): Long =
  elapsedDays(dob, target) / 7

This calculates complete groups of seven elapsed days and should be presented as a duration rather than as an alternative definition of calendar age.

Validate and Parse a Date of Birth

LocalDate.of performs calendar validation. For text input, controlled error handling prevents malformed user input from terminating the application unexpectedly.

import java.time.LocalDate
import java.time.format.DateTimeParseException

def parseDob(text: String): Either[String, LocalDate] =
  try Right(LocalDate.parse(text))
  catch
    case _: DateTimeParseException =>
      Left("Enter a valid date in ISO format YYYY-MM-DD")

LocalDate.parse naturally accepts ISO-style input such as 2000-03-15. A custom DateTimeFormatter can be supplied when an application accepts another format.

Leap Years and February 29

Leap-year cases are handled by the Java date/time API rather than hard-coded month lengths. Java’s date-time documentation shows that February has 28 days in a common year and 29 in a leap year, and Year.isLeap can explicitly test the leap-year rule.

Birth dateTarget dateWhat to test
2000-02-292024-02-28Birthday boundary immediately before February 29.
2000-02-292024-02-29Exact leap-day birthday.
2000-02-292025-03-01Post-birthday behavior in a non-leap year.

If a business or eligibility system has a special rule for February 29 in a non-leap year, encode that rule explicitly. Different applications can define the boundary differently.

Period vs Total Days

CalculationMeaningAPI
Completed yearsWhole calendar years represented by the date difference.Period.between(...).getYears
Years, months, daysCalendar breakdown between two dates.Period.between
Total daysElapsed calendar days.ChronoUnit.DAYS.between
Total weeksComplete seven-day groups.Days divided by 7

Build a Reusable Scala Age Calculator

import java.time.LocalDate
import java.time.Period
import java.time.temporal.ChronoUnit

final case class Age(
  years: Int,
  months: Int,
  days: Int,
  totalDays: Long
)

object AgeCalculator:
  def calculate(dob: LocalDate, target: LocalDate): Age =
    require(!target.isBefore(dob), "target date is before date of birth")

    val period = Period.between(dob, target)
    val days = ChronoUnit.DAYS.between(dob, target)

    Age(
      period.getYears,
      period.getMonths,
      period.getDays,
      days
    )

A small immutable case class makes the output easy to pass between application layers. The calculator keeps calendar age and total elapsed days as separate values, avoiding confusion between two different measurements.

Format Dates with DateTimeFormatter

import java.time.format.DateTimeFormatter

val formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy")
val dob = LocalDate.parse("15/03/2000", formatter)
println(dob.format(formatter))

For APIs and data storage, ISO dates such as yyyy-MM-dd are convenient to exchange. For user interfaces, a formatter can present the same underlying LocalDate in another convention.

LocalDate vs LocalDateTime

LocalDate represents only a date. LocalDateTime adds a local clock time but still does not contain a time zone. Java’s documentation explicitly describes LocalDateTime as a date-time without a time zone.

For a conventional birthday calculator, LocalDate is the clearer model. If you need the exact instant of birth, time-zone conversions, or age measured in hours, use an appropriate instant or zoned date-time type and define the application’s time-zone semantics.

Time Zones and Birthday Calculations

A date-only birthday normally does not need a time zone. A timestamp near midnight does. An instant can correspond to different local calendar dates in different zones, so an application calculating age from birth timestamps should decide which local date defines the birthday.

Age Calculator on a Web Server

When running Scala on a server, keep the target date explicit in the core function. The outer application can obtain today’s date and pass it into the calculation. This makes tests deterministic and avoids hiding a system-clock dependency inside the business logic.

def calculateAgeOn(dob: LocalDate, target: LocalDate): Int =
  require(!target.isBefore(dob))
  Period.between(dob, target).getYears

Testing an Age Calculator in Scala

Test boundaries rather than only ordinary dates. Useful cases include the day before a birthday, the birthday itself, the day after, leap-day births, invalid dates, month ends, and a target date before the date of birth.

TestPurpose
Birthday todayChecks the year increment boundary.
Day before birthdayPrevents premature age increments.
Day after birthdayChecks normal post-birthday behavior.
February 29Checks leap-year handling.
Invalid inputChecks parser and date validation.
Target before DOBPrevents negative-age results.

Common Scala Age Calculator Mistakes

  • Dividing total days by 365 and treating that as calendar age.
  • Ignoring whether the birthday has occurred in the target year.
  • Using legacy java.util.Date for a date-only birthday when java.time is available.
  • Mixing LocalDate and timestamps without defining the time-zone rule.
  • Accepting malformed text without handling DateTimeParseException.
  • Allowing a target date before the date of birth.
  • Using a fixed approximation for the number of days in a month.
Scala REPL HelloWorld example for programming language article
Scala REPL HelloWorld screenshot by Siskus, Wikimedia Commons, available under CC BY-SA licenses.

Scala Age Calculator Example

import java.time.LocalDate
import java.time.Period

@main def ageCalculator(): Unit =
  val dob = LocalDate.of(1990, 11, 24)
  val today = LocalDate.now
  val period = Period.between(dob, today)

  println("Completed age: " + period.getYears)
  println(
    "Calendar age: " + period.getYears + " years, " +
    period.getMonths + " months, " + period.getDays + " days"
  )

This compact Scala 3 example uses immutable values, Java’s standard date API, and straightforward string concatenation. It can be expanded into a command-line calculator or connected to a web form that supplies the date of birth.

How Scala Compares with Other Age Calculator Implementations

The calendar problem is similar across languages, but the APIs differ. Scala can directly use Java’s java.time classes, while other languages expose their own date libraries or standard-library types. Related tutorials include Java, Kotlin, Rust, Go, Haskell, Elixir, Julia, and OCaml.

LanguageDate approachUseful age concept
ScalaJava LocalDate and PeriodCalendar periods through Java interoperability.
Javajava.timeLocalDate, Period, and date units.
KotlinJVM date/time APIsCalendar-aware date calculations.
RustRust date/time ecosystemTyped date arithmetic.
OCamlCalendarLibFunctional calendar periods.

Frequently Asked Questions

Can Scala calculate age without a third-party date library?

Yes. Scala can use the Java standard library’s java.time API directly. Scala’s documentation demonstrates this Java interoperability for date and time classes.

What Scala type should I use for a date of birth?

java.time.LocalDate is a natural choice when the birth information is a calendar date without a time. It represents year-month-day without a time zone.

How do I calculate age in years, months and days?

Use Period.between(dob, target), then read getYears, getMonths, and getDays. Java documents Period as a years-months-days date-based amount.

How do I calculate total days between two dates?

Use ChronoUnit.DAYS.between(dob, target). This is a duration-style day count and should not be substituted for calendar age.

Does Scala handle leap years?

Yes, when you use the Java date/time API. The ISO calendar rules used by LocalDate and related classes account for leap years, and Java also exposes explicit leap-year checks such as Year.isLeap.

Official Scala and Java References

Image Credits

The Scala logo is from Wikimedia Commons and is identified there as a public-domain text logo. The Scala REPL screenshot is by Siskus and is available under CC BY-SA licenses listed on its Wikimedia Commons file page.

Final Takeaway

An age calculator in Scala can stay concise by using the Java java.time API. Use LocalDate for a date-only birthday, Period.between for calendar years-months-days, and ChronoUnit.DAYS when the application specifically needs elapsed days. Keep the target date explicit in reusable functions, validate input, test birthday and leap-day boundaries, and define time-zone rules whenever exact timestamps are involved.