DateTimeFormatter in Java

Naveen AnamaneniUpdated · 4 min read

The DateTimeFormatter class in Java, in java.time.format, is used to format a date or time as text, such as turning 2026-11-12 into "12 Nov 2026", and to parse text back into a date or time. It replaces the old SimpleDateFormat, and unlike that class it is immutable and thread-safe, so one formatter can be shared everywhere. In this lesson, you will learn the built-in formatters, how to write your own patterns, and how to handle parsing errors.

Creating a Formatter

WayExample
A built-in ISO formatterDateTimeFormatter.ISO_LOCAL_DATE
A patternDateTimeFormatter.ofPattern("dd-MM-yyyy")
A pattern in a languageDateTimeFormatter.ofPattern("d MMMM yyyy", Locale.FRENCH)
A localized styleDateTimeFormatter.ofLocalizedDate(FormatStyle.LONG)

Pattern Letters

LetterMeaningExample
yyyyYear2026
MM / MMM / MMMMMonth as number, short name, full name11 / Nov / November
dd / dDay of month, with or without a leading zero05 / 5
EEE / EEEEDay of week, short or fullThu / Thursday
HHHour, 0 to 2314
hhHour, 1 to 1202
mmMinute (lowercase!)47
ssSecond31
aAM or PMPM
VV / zZone ID or zone nameAsia/Kolkata / IST
'text'Literal text in quotes'at'

Example: Formatting

Let's see an example that formats one date and time in several ways.

Formatting.java▶ Try it
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
 
public class Formatting {
    public static void main(String[] args) {
        LocalDateTime t = LocalDateTime.of(2026, 11, 12, 14, 47, 31);
 
        System.out.println(t.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        System.out.println(t.format(DateTimeFormatter.ofPattern("dd-MM-yyyy")));
        System.out.println(t.format(
            DateTimeFormatter.ofPattern("EEEE, d MMMM yyyy", Locale.ENGLISH)));
        System.out.println(t.format(
            DateTimeFormatter.ofPattern("hh:mm a", Locale.ENGLISH)));
        System.out.println(t.format(DateTimeFormatter.ofPattern(
            "'Exam on' dd MMM 'at' HH:mm", Locale.ENGLISH)));
        System.out.println(t.format(
            DateTimeFormatter.ofPattern("d MMMM yyyy", Locale.FRENCH)));
    }
}
Output
2026-11-12T14:47:31
12-11-2026
Thursday, 12 November 2026
02:47 PM
Exam on 12 Nov at 14:47
12 novembre 2026

Explanation: The ISO formatter gives the standard machine format. Each pattern lays out the parts you choose. Words in single quotes are copied as they are. The locale decides the language of month and day names, so the same pattern gives "November" in English and "novembre" in French.

Example: Parsing

Parsing.java▶ Try it
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.format.ResolverStyle;
 
public class Parsing {
    public static void main(String[] args) {
        DateTimeFormatter indian = DateTimeFormatter.ofPattern("dd/MM/yyyy");
 
        LocalDate birthday = LocalDate.parse("15/03/2012", indian);
        System.out.println("Parsed: " + birthday + ", a "
            + birthday.getDayOfWeek());
 
        LocalTime alarm = LocalTime.parse("06:30");
        System.out.println("Alarm: " + alarm);
 
        System.out.println("Smart: " + LocalDate.parse("31/02/2026", indian));
 
        DateTimeFormatter strict = DateTimeFormatter.ofPattern("dd/MM/uuuu")
            .withResolverStyle(ResolverStyle.STRICT);
        try {
            LocalDate.parse("31/02/2026", strict);
        } catch (DateTimeParseException e) {
            System.out.println("Strict: " + e.getMessage());
        }
    }
}
Output
Parsed: 2012-03-15, a THURSDAY
Alarm: 06:30
Smart: 2026-02-28
Strict: Text '31/02/2026' could not be parsed: Invalid date 'FEBRUARY 31'

Explanation: LocalDate.parse(text, formatter) reads text using the pattern. Without a formatter, parse expects ISO text such as "06:30". Note the surprise: by default, a formatter uses the smart resolver, which quietly turns 31 February into 28 February. A formatter with ResolverStyle.STRICT rejects it with DateTimeParseException. Strict mode needs uuuu (the proleptic year) instead of yyyy. Text that can never be valid, such as day 32, throws even in smart mode.

Common Mistakes

Writing "dd-mm-yyyy". mm is minutes; use MM for months.

Writing "YYYY". Y is the week-based year, which differs from the calendar year around New Year; use yyyy.

Validating user input with the default (smart) resolver. It turns 31 February into 28 February; use ResolverStyle.STRICT with uuuu.

Formatting month names without a locale. The result depends on the computer's language; pass Locale.ENGLISH or the user's locale.

Interview Corner

Why is DateTimeFormatter preferred over SimpleDateFormat?

DateTimeFormatter is immutable and thread-safe, so a single instance can be shared, whereas SimpleDateFormat keeps internal state and gives wrong results when shared between threads. DateTimeFormatter works with the java.time types, has strict and clear parsing errors through DateTimeParseException, and offers built-in ISO and localized formats.

Practice

  1. Easy: Format today's date as "Thursday 12/11/2026" and as "12th of November" (hint: build the "th" yourself).
  2. Harder: Read dates typed in the format dd-MM-yyyy, ask again when the input is invalid, and print how many days remain until each date.

Quick check: DateTimeFormatter

4 questions
1Which pattern letter means month?
2Is DateTimeFormatter thread-safe?
3With the default smart resolver, what does parsing "31/02/2026" with "dd/MM/yyyy" give?
4How do you include literal words in a pattern?

Key Takeaways

Was this tutorial helpful?

Lesson 334 of 482