Java DateTimeFormatter Class

DateTimeFormatter is an important class in the date-time API (java.time package) introduced in Java 8. It is used to format and parse date-time objects. This class provides powerful functionality for handling the display and conversion of date-time values.

In simple terms, DateTimeFormatter has two main purposes:

  • Formatting: Converts date-time objects (such as LocalDate, LocalDateTime) to strings in a specific format
  • Parsing: Converts strings that match a format to date-time objects

Why Do You Need DateTimeFormatter

Before Java 8, we used SimpleDateFormat to handle date formatting and parsing, but it has several drawbacks:

  • Not thread-safe
  • Outdated design
  • Unfriendly error handling

DateTimeFormatter solves these problems:

  • Thread safety: Instances can be safely shared in multi-threaded environments
  • Immutable: Once created, it cannot be modified
  • Richer predefined formats: Provides a large number of built-in formats
  • Better error handling: Provides more detailed error information when parsing fails

Basic Usage

Predefined Formatters

DateTimeFormatter provides many predefined formatter constants:

Example

LocalDateTime now = LocalDateTime.now();

// Use a predefined formatter
System.out.println(now.format(DateTimeFormatter.ISO_LOCAL_DATE));     // 2023-11-15
System.out.println(now.format(DateTimeFormatter.ISO_LOCAL_TIME));     // 14:30:45.123
System.out.println(now.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); // 2023-11-15T14:30:45.123

Custom Patterns

You can create custom formatters using pattern strings:

Example

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formattedDateTime = now.format(formatter);  // Formatting
System.out.println(formattedDateTime);             // 2023-11-15 14:30:45

// Parsing
LocalDateTime parsedDateTime = LocalDateTime.parse("2023-11-15 14:30:45", formatter);

// Common Chinese date format
DateTimeFormatter chineseFormatter = DateTimeFormatter.ofPattern(yyyy-MM-dd);
String formattedDate = today.format(chineseFormatter);
System.out.println(Chinese-format date: + formattedDate);

// Parse Chinese date string
String chineseDateStr = 2023-05-20;
LocalDate parsedDate = LocalDate.parse(chineseDateStr, chineseFormatter);
System.out.println(Parsed date: + parsedDate);

// Other common formats
DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("MM/dd/yyyy");
DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern(yyyy-MM-dd EEEE, Locale.CHINA);

System.out.println(Format 1: + today.format(formatter1));
System.out.println(Format 2: + today.format(formatter2));
System.out.println(Format 3 (with weekday): + today.format(formatter3));

Localized Formats

You can create formatters based on different locales:

Example

DateTimeFormatter frenchFormatter =
    DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG)
                     .withLocale(Locale.FRENCH);
String frenchDate = now.format(frenchFormatter);
System.out.println(frenchDate);  // 15 novembre 2023

Pattern Letter Reference

When creating custom formats, you need to use specific pattern letters:

Letter Meaning Example
y year yyyy → 2023
M month MM → 11
d day dd → 15
H Hour (0-23) HH → 14
h Hour (1-12) hh → 02
m Minute mm → 30
s second ss → 45
S Millisecond SSS → 123
E Day of the week E → Wed
a AM/PM a → PM

Best Practices

Reuse Formatters

Since DateTimeFormatter is thread-safe, it is recommended to define commonly used formatters as constants:

Example

public class DateUtils {
    public static final DateTimeFormatter STANDARD_FORMATTER =
        DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
   
    // Usage
    String formatted = LocalDateTime.now().format(STANDARD_FORMATTER);
}

Comprehensive example:

Example

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class ExampleTest {

    public static void main(String[] args) {
        // 1. LocalDate example
        LocalDate currentDate = LocalDate.now();
        System.out.println(Current date: + currentDate);
       
        LocalDate specificDate = LocalDate.of(2023, 5, 20);
        System.out.println(Specific date: + specificDate);

        // 2. LocalTime example
        LocalTime currentTime = LocalTime.now();
        System.out.println(Current time: + currentTime);
       
        LocalTime specificTime = LocalTime.of(14, 30, 15);
        System.out.println(Specific time: + specificTime);

        // 3. LocalDateTime example
        LocalDateTime currentDateTime = LocalDateTime.now();
        System.out.println(Current date and time: + currentDateTime);
       
        LocalDateTime specificDateTime = LocalDateTime.of(2023, 5, 20, 14, 30, 15);
        System.out.println(Specific date and time: + specificDateTime);

        // 4. DateTimeFormatter example
        // Basic formatting
        DateTimeFormatter basicFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        System.out.println(Basic formatting: + currentDate.format(basicFormatter));

        // Chinese formatting
        DateTimeFormatter chineseFormatter = DateTimeFormatter.ofPattern(yyyy-MM-dd, Locale.CHINA);
        System.out.println(Chinese date: + currentDate.format(chineseFormatter));

        // Chinese formatting with weekday
        DateTimeFormatter weekFormatter = DateTimeFormatter.ofPattern(yyyy-MM-dd EEEE, Locale.CHINA);
        System.out.println(Chinese date with weekday: + currentDate.format(weekFormatter));

        // Time formatting
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(HH:mm:ss);
        System.out.println(Chinese time: + currentTime.format(timeFormatter));

        // Date-time formatting
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        System.out.println(Standard date and time: + currentDateTime.format(dateTimeFormatter));

        // Parse date
        String dateStr = "2023-05-20";
        LocalDate parsedDate = LocalDate.parse(dateStr, basicFormatter);
        System.out.println(Parsed date: + parsedDate);

        // Parse Chinese date
        String chineseDateStr = 2023-05-20;
        LocalDate parsedChineseDate = LocalDate.parse(chineseDateStr, chineseFormatter);
        System.out.println(Parsed Chinese date: + parsedChineseDate);
    }
}

The output is:

当前日期: 2025-05-01
特定日期: 2023-05-20
当前时间: 10:46:38.591747
特定时间: 14:30:15
当前日期时间: 2025-05-01T10:46:38.592002
特定日期时间: 2023-05-20T14:30:15
基本格式化: 2025-05-01
中文日期: 2025年05月01日
带星期的中文日期: 2025年05月01日 星期四
中文时间: 10时46分38秒
标准日期时间: 2025-05-01 10:46:38
解析后的日期: 2023-05-20
解析后的中文日期: 2023-05-20

Handling Parse Exceptions

You should handle possible exceptions when parsing strings:

Example

try {
    LocalDateTime dateTime = LocalDateTime.parse("2023-11-15", formatter);
} catch (DateTimeParseException e) {
    System.err.println(Unable to parse date/time: + e.getMessage());
}

Consider Time Zones

If you need to handle time zones, you can useZonedDateTimeand specific time zone patterns:

Example

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
System.out.println(zonedDateTime.format(formatter));  // 2023-11-15 14:30:45 CST

Summary

DateTimeFormatter is a powerful tool for formatting and parsing in the Java 8 date-time API. Compared with the old SimpleDateFormat, it is safer, more flexible, and easier to use. Mastering DateTimeFormatter allows you to handle various date-time format requirements more efficiently.

Remember the key points:

  • Use predefined formatters for common formats
  • Use ofPattern() to create custom formats
  • Consider localization and time zone requirements
  • Reuse thread-safe formatter instances
  • Handle parse exceptions correctly
Other extensions