Scala 3 dates: How to format dates (DateTimeFormatter, LocalDate) in Scala

This is an excerpt from the Scala Cookbook, 2nd Edition. This is Recipe 3.11, Formatting Dates in Scala.

Problem

While using Scala (2 or 3), you want to format dates, such as for printing them out in a desired format.

Solution: Scala date formatting

The solution is to use the java.time.format.DateTimeFormatter class. It provides three types of formatters for printing date/time values:

  • Predefined formatters
  • Locale formatters
  • The ability to create your own custom formatters

Predefined formatters

DateTimeFormatter provides fifteen predefined formatters you can use. This example shows how to use a formatter with a LocalDate:

import java.time.LocalDate
import java.time.format.DateTimeFormatter
val d = LocalDate.now   // 2021-02-04

val f = DateTimeFormatter.BASIC_ISO_DATE
f.format(d)             // 20210204

These examples show what the other date formatters look like:

ISO_LOCAL_DATE     // 2021-02-04
ISO_DATE           // 2021-02-04
BASIC_ISO_DATE     // 20210204
ISO_ORDINAL_DATE   // 2021-035
ISO_WEEK_DATE      // 2021-W05-4

Locale formatters

Create locale formatters using these static DateTimeFormatter methods:

  • ofLocalizedDate
  • ofLocalizedTime
  • ofLocalizedDateTime

You also apply one of four java.time.format.FormatStyle values when creating a localized date:

  • SHORT
  • MEDIUM
  • LONG
  • FULL

This example demonstrates how to use ofLocalizedDate with a LocalDate and FormatStyle.FULL:

import java.time.LocalDate
import java.time.format.{DateTimeFormatter, FormatStyle}

val d = LocalDate.of(2021, 1, 1)
val f = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)
f.format(d)   // Friday, January 1, 2021

Using the same technique, this is what the four format styles look like:

SHORT    // 1/1/21
MEDIUM   // Jan 1, 2021
LONG     // January 1, 2021
FULL     // Friday, January 1, 2021

Custom patterns with ofPattern

You can also create custom patterns by specifying your own formatting strings. Here’s an example of the technique:

import java.time.LocalDate
import java.time.format.DateTimeFormatter

val d = LocalDate.now  // 2021-01-01
val f = DateTimeFormatter.ofPattern("yyyy-MM-dd")
f.format(d)            // 2021-01-01

Here are a few other common patterns:

"MM/dd/yyyy"       // 01/01/2021
"MMM dd, yyyy"     // Jan 01, 2021
"E, MMM dd yyyy"   // Fri, Jan 01 2021

This example demonstrates how to format a LocalTime:

import java.time.LocalTime
import java.time.format.DateTimeFormatter

val t = LocalTime.now
val f1 = DateTimeFormatter.ofPattern("h:mm a")
f1.format(t)   // 6:48 PM

val f2 = DateTimeFormatter.ofPattern("HH:mm:ss a")
f2.format(t)   // 18:48:33 PM

With a LocalDateTime you can format both date and time output:

import java.time.LocalDateTime
import java.time.format.DateTimeFormatter

val t = LocalDateTime.now
val f = DateTimeFormatter.ofPattern("MMM dd, yyyy h:mm a")
f.format(t)   // Jan 01, 2021 6:48 PM

See the DateTimeFormatter class for a complete list of predefined formats and formatting pattern characters that are available.