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.

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.LocalDateandjava.time.Period. - Represent the date of birth as a
LocalDate. - Use
LocalDate.nowfor today’s date or supply a fixed target date. - Use
Period.betweenfor a calendar years-months-days result. - Use
ChronoUnit.DAYSwhen 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.PeriodThese 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.nowFor 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).getYearsPeriod.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) / 7This 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 date | Target date | What to test |
|---|---|---|
| 2000-02-29 | 2024-02-28 | Birthday boundary immediately before February 29. |
| 2000-02-29 | 2024-02-29 | Exact leap-day birthday. |
| 2000-02-29 | 2025-03-01 | Post-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
| Calculation | Meaning | API |
|---|---|---|
| Completed years | Whole calendar years represented by the date difference. | Period.between(...).getYears |
| Years, months, days | Calendar breakdown between two dates. | Period.between |
| Total days | Elapsed calendar days. | ChronoUnit.DAYS.between |
| Total weeks | Complete 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).getYearsTesting 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.
| Test | Purpose |
|---|---|
| Birthday today | Checks the year increment boundary. |
| Day before birthday | Prevents premature age increments. |
| Day after birthday | Checks normal post-birthday behavior. |
| February 29 | Checks leap-year handling. |
| Invalid input | Checks parser and date validation. |
| Target before DOB | Prevents 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.Datefor a date-only birthday whenjava.timeis available. - Mixing
LocalDateand 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 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.
| Language | Date approach | Useful age concept |
|---|---|---|
| Scala | Java LocalDate and Period | Calendar periods through Java interoperability. |
| Java | java.time | LocalDate, Period, and date units. |
| Kotlin | JVM date/time APIs | Calendar-aware date calculations. |
| Rust | Rust date/time ecosystem | Typed date arithmetic. |
| OCaml | CalendarLib | Functional 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
- Scala for Java Programmers — official Scala documentation.
- Why Scala 3? — official Scala 3 documentation on Java integration.
- Java LocalDate API — official Java API reference.
- Java Period API — official Java API reference.
- Java ChronoUnit API — official Java API reference.
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.