Java DateTimeFormatter Class
Last modified: April 16, 2025
The java.time.format.DateTimeFormatter
class provides formatting
and parsing of date-time objects. It is part of Java's modern date-time API
introduced in Java 8. The class is thread-safe and immutable.
DateTimeFormatter
supports predefined formatters, pattern-based
formatting, and localized styles. It works with all temporal classes like
LocalDate, LocalDateTime, and ZonedDateTime. The class handles both formatting
dates to strings and parsing strings to dates.
DateTimeFormatter Class Overview
DateTimeFormatter
provides constants for common formats and methods
to create custom patterns. Key features include locale-sensitive formatting,
pattern syntax similar to SimpleDateFormat, and strict parsing rules.
public final class DateTimeFormatter { public static DateTimeFormatter ofPattern(String pattern); public static DateTimeFormatter ofPattern(String pattern, Locale locale); public static DateTimeFormatter ofLocalizedDate(FormatStyle dateStyle); public String format(TemporalAccessor temporal); public TemporalAccessor parse(CharSequence text); public TemporalAccessor parse(CharSequence text, ParsePosition position); public DateTimeFormatter withLocale(Locale locale); public DateTimeFormatter withResolverStyle(ResolverStyle resolverStyle); }
The code above shows key methods of DateTimeFormatter
. The class
provides flexible formatting options while maintaining thread safety. It replaces
the older SimpleDateFormat
which had thread-safety issues.
Using Predefined Formatters
Java provides several predefined formatters for common ISO and localized formats. These constants are available as static fields in DateTimeFormatter. They cover most standard date-time representations.
package com.zetcode; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; public class Main { public static void main(String[] args) { LocalDateTime now = LocalDateTime.now(); // ISO date time System.out.println("ISO_DATE_TIME: " + now.format(DateTimeFormatter.ISO_DATE_TIME)); // ISO date System.out.println("ISO_DATE: " + now.format(DateTimeFormatter.ISO_DATE)); // ISO time System.out.println("ISO_TIME: " + now.format(DateTimeFormatter.ISO_TIME)); // Basic ISO date (without separators) System.out.println("BASIC_ISO_DATE: " + now.format(DateTimeFormatter.BASIC_ISO_DATE)); } }
This example demonstrates using predefined ISO formatters. The output shows different standard representations of the current date and time. These formatters are useful when working with standardized date formats.
Formatting with Custom Patterns
Custom patterns can be created using the ofPattern
method. The
pattern syntax uses letters to represent date/time components. The patterns
are similar to those used in SimpleDateFormat.
package com.zetcode; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; public class Main { public static void main(String[] args) { LocalDateTime now = LocalDateTime.now(); // Custom pattern with date and time DateTimeFormatter formatter1 = DateTimeFormatter .ofPattern("yyyy-MM-dd HH:mm:ss"); System.out.println("Custom 1: " + now.format(formatter1)); // Pattern with month name and day of week DateTimeFormatter formatter2 = DateTimeFormatter .ofPattern("EEEE, MMMM dd, yyyy"); System.out.println("Custom 2: " + now.format(formatter2)); // Pattern with 12-hour clock DateTimeFormatter formatter3 = DateTimeFormatter .ofPattern("hh:mm a"); System.out.println("Custom 3: " + now.format(formatter3)); // Pattern with time zone (for ZonedDateTime) DateTimeFormatter formatter4 = DateTimeFormatter .ofPattern("MM/dd/yyyy HH:mm z"); } }
This example shows various custom formatting patterns. The patterns can include literal text and special pattern letters. Note that some patterns require specific temporal types (like time zones with ZonedDateTime).
Localized Formatting
DateTimeFormatter
supports locale-specific formatting through
ofLocalized
methods and withLocale
. This produces
output appropriate for different languages and regional conventions.
package com.zetcode; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.FormatStyle; import java.util.Locale; public class Main { public static void main(String[] args) { LocalDateTime now = LocalDateTime.now(); // Short format for current locale DateTimeFormatter shortFormatter = DateTimeFormatter .ofLocalizedDateTime(FormatStyle.SHORT); System.out.println("Short format: " + now.format(shortFormatter)); // Medium format for French locale DateTimeFormatter mediumFrench = DateTimeFormatter .ofLocalizedDateTime(FormatStyle.MEDIUM) .withLocale(Locale.FRENCH); System.out.println("French medium: " + now.format(mediumFrench)); // Full date with German locale DateTimeFormatter fullGerman = DateTimeFormatter .ofLocalizedDate(FormatStyle.FULL) .withLocale(Locale.GERMAN); System.out.println("German full date: " + now.format(fullGerman)); } }
This example demonstrates locale-sensitive formatting. The output varies based on the specified locale and format style. FormatStyle offers SHORT, MEDIUM, LONG, and FULL options for different detail levels.
Parsing Date-Time Strings
DateTimeFormatter
can parse strings into date-time objects. The
parse method converts text following the formatter's pattern into a temporal
object. Strict parsing ensures input validity.
package com.zetcode; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; public class Main { public static void main(String[] args) { // Parse ISO date LocalDate date = LocalDate.parse("2025-12-31"); System.out.println("Parsed date: " + date); // Parse with custom formatter DateTimeFormatter formatter = DateTimeFormatter .ofPattern("MM/dd/yyyy HH:mm"); LocalDateTime dateTime = LocalDateTime.parse("12/25/2025 14:30", formatter); System.out.println("Parsed date-time: " + dateTime); // Parse with locale DateTimeFormatter frenchFormatter = DateTimeFormatter .ofPattern("d MMMM yyyy", java.util.Locale.FRENCH); LocalDate frenchDate = LocalDate.parse("25 décembre 2025", frenchFormatter); System.out.println("Parsed French date: " + frenchDate); } }
This example shows parsing strings into date-time objects. The parser is strict
by default, rejecting invalid dates. For lenient parsing, use
withResolverStyle(ResolverStyle.LENIENT)
.
Formatting ZonedDateTime
When working with time zones, DateTimeFormatter
can handle
zone-specific formatting. The patterns can include zone IDs or offsets.
ZonedDateTime provides complete timezone-aware date-time information.
package com.zetcode; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.ZoneId; public class Main { public static void main(String[] args) { ZonedDateTime zonedNow = ZonedDateTime.now(ZoneId.of("America/New_York")); // Format with zone ID DateTimeFormatter formatter1 = DateTimeFormatter .ofPattern("yyyy-MM-dd HH:mm z"); System.out.println("With zone: " + zonedNow.format(formatter1)); // Format with zone offset DateTimeFormatter formatter2 = DateTimeFormatter .ofPattern("yyyy-MM-dd HH:mm XXX"); System.out.println("With offset: " + zonedNow.format(formatter2)); // Format with zone name DateTimeFormatter formatter3 = DateTimeFormatter .ofPattern("yyyy-MM-dd HH:mm VV"); System.out.println("With zone name: " + zonedNow.format(formatter3)); } }
This example demonstrates formatting ZonedDateTime with time zone information. Different pattern letters handle zone IDs, offsets, and names. The output shows the same moment in time with different zone representations.
Combining Formatters
DateTimeFormatter
instances can be combined or modified using
methods like withLocale
and withResolverStyle
.
This allows creating flexible formatters from existing ones.
package com.zetcode; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.FormatStyle; import java.time.format.ResolverStyle; import java.util.Locale; public class Main { public static void main(String[] args) { LocalDateTime now = LocalDateTime.now(); // Create base formatter DateTimeFormatter base = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); // Add locale DateTimeFormatter withLocale = base.withLocale(Locale.GERMAN); System.out.println("With German locale: " + now.format(withLocale)); // Change to strict resolver DateTimeFormatter strict = base.withResolverStyle(ResolverStyle.STRICT); // Combine with localized time formatter DateTimeFormatter combined = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT) .withLocale(Locale.FRENCH); System.out.println("Combined French time: " + now.format(combined)); } }
This example shows how to modify and combine formatters. The resolver style controls how lenient the parsing should be. Combined formatters can mix pattern-based and localized formatting.
Source
Java DateTimeFormatter Class Documentation
In this article, we've covered the essential methods and features of the Java DateTimeFormatter class. Mastering these concepts is crucial for effective date-time handling in Java applications.
Author
List all Java tutorials.