Java DateTimeFormatter Tutorial with Examples

DateTimeFormatter class is a formatter for printing and parsing date-time objects since the introduction of Java 8 date time API.

Create DateTimeFormatter

You can create DateTimeFormatter in two ways:

  • Use inbuilt pattern constants
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;

  • Use ofPattern() method
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy hh:mm:ss");

Predefined Formatters

DateTimeFormatter comes with multiple predefined date/time formats that follow ISO and RFC standards:

DateTimeFormatterPredefinedExample.java
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;

public class DateTimeFormatterPredefinedExample {
    
    static void print(String format, String result) {
        System.out.printf("%s: %s\n", format, result);
    }
    
    public static void main(String[] args) {    
        print("ofLocalizedDate(*)", DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG).format(LocalDate.now()));
        print("ofLocalizedTime(*)", DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM).format(LocalTime.now()));
        print("ofLocalizedDateTime(*)", DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).format(LocalDateTime.now()));
        print("ofLocalizedDateTime(*, *)", DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL, FormatStyle.SHORT).format(LocalDateTime.now()));
        
        print("BASIC_ISO_DATE", DateTimeFormatter.BASIC_ISO_DATE.format(LocalDate.now()));
        print("ISO_LOCAL_DATE", DateTimeFormatter.ISO_LOCAL_DATE	.format(LocalDate.now()));
        print("ISO_OFFSET_DATE", DateTimeFormatter.ISO_OFFSET_DATE.format(OffsetDateTime.now()));
        print("ISO_DATE", DateTimeFormatter.ISO_DATE.format(OffsetDateTime.now()));
        print("ISO_LOCAL_TIME", DateTimeFormatter.ISO_LOCAL_TIME.format(LocalTime.now()));
        print("ISO_OFFSET_TIME", DateTimeFormatter.ISO_OFFSET_TIME.format(OffsetTime.now()));
        print("ISO_TIME", DateTimeFormatter.ISO_TIME.format(OffsetTime.now()));
        print("ISO_LOCAL_DATE_TIME", DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(LocalDateTime.now()));
        print("ISO_OFFSET_DATE_TIME", DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(OffsetDateTime.now()));
        print("ISO_ZONED_DATE_TIME", DateTimeFormatter.ISO_ZONED_DATE_TIME.format(ZonedDateTime.now()));
        print("ISO_DATE_TIME", DateTimeFormatter.ISO_DATE_TIME.format(ZonedDateTime.now()));
        print("ISO_ORDINAL_DATE", DateTimeFormatter.ISO_ORDINAL_DATE.format(ZonedDateTime.now()));
        print("ISO_WEEK_DATE", DateTimeFormatter.ISO_WEEK_DATE.format(ZonedDateTime.now()));
        print("ISO_INSTANT", DateTimeFormatter.ISO_INSTANT.format(ZonedDateTime.now()));
        print("RFC_1123_DATE_TIME", DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now()));
    }
}
                    

ofLocalizedDate(*): 3 September, 2019
ofLocalizedTime(*): 12:28:39 AM
ofLocalizedDateTime(*): 3 Sep, 2019 12:28:39 AM
ofLocalizedDateTime(*, *): Tuesday, 3 September, 2019 12:28 AM
BASIC_ISO_DATE: 20190903
ISO_LOCAL_DATE: 2019-09-03
ISO_OFFSET_DATE: 2019-09-03+08:00
ISO_DATE: 2019-09-03+08:00
ISO_LOCAL_TIME: 00:28:39.275
ISO_OFFSET_TIME: 00:28:39.277+08:00
ISO_TIME: 00:28:39.278+08:00
ISO_LOCAL_DATE_TIME: 2019-09-03T00:28:39.278
ISO_OFFSET_DATE_TIME: 2019-09-03T00:28:39.278+08:00
ISO_ZONED_DATE_TIME: 2019-09-03T00:28:39.279+08:00[Asia/Singapore]
ISO_DATE_TIME: 2019-09-03T00:28:39.279+08:00[Asia/Singapore]
ISO_ORDINAL_DATE: 2019-246+08:00
ISO_WEEK_DATE: 2019-W36-2+08:00
ISO_INSTANT: 2019-09-02T16:28:39.280Z
RFC_1123_DATE_TIME: Tue, 3 Sep 2019 00:28:39 +0800

Each of these predefined DateTimeFormatter instances are preconfigured to format and parse date/times to/from different formats.

Using FormatStyle

In our examples earlier, we use FormatStyle to define on which format used for our date/time (see functions ofLocalizedDate(), ofLocalizedTime(), and ofLocalizedDateTime()). FormatStyle is an enumeration of the style of a localized date, time or date-time formatter. There are four constants:

  • FULL: Full text style, with the most detail.
  • LONG: Long text style, with lots of detail.
  • MEDIUM: Medium text style, with some detail.
  • SHORT: Short text style, typically numeric.
DateTimeFormatterFormatStyleExample.java
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;

public class DateTimeFormatterFormatStyleExample {
    
    static void print(String format, String result) {
        System.out.printf("%s: %s\n", format, result);
    }
    
    public static void main(String[] args) {
        LocalDate localDate = LocalDate.now();
        System.out.println("*** LocalDate ***");
        print("FULL", DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).format(localDate));
        print("LONG", DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG).format(localDate));
        print("MEDIUM", DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).format(localDate));
        print("SHORT", DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).format(localDate));
        
        LocalTime localTime = LocalTime.now();
        System.out.println("\n*** LocalTime ***");
        print("MEDIUM", DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM).format(localTime));
        print("SHORT", DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT).format(localTime));
        
        LocalDateTime localDateTime = LocalDateTime.now();
        System.out.println("\n*** LocalDateTime ***");
        print("MEDIUM", DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).format(localDateTime));
        print("SHORT", DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).format(localDateTime));
    }
}
                    

*** LocalDate ***
FULL: Tuesday, 3 September, 2019
LONG: 3 September, 2019
MEDIUM: 3 Sep, 2019
SHORT: 3/9/19

*** LocalTime ***
MEDIUM: 2:05:19 AM
SHORT: 2:05 AM

*** LocalDateTime ***
MEDIUM: 3 Sep, 2019 2:05:19 AM
SHORT: 3/9/19 2:05 AM

If the FormatStyle is not supported in LocalTime, following exception will be thrown:

java.time.DateTimeException: Unable to extract value: class java.time.format.DateTimePrintContext$1

And if the FormatStyle is not supported in LocalDateTime:

java.time.DateTimeException: Unable to extract value: class java.time.LocalDateTime

Format Date/Time to String

We use format(...) method to convert Date/Time (in this case TemporalAccessor) to String:

LocalDateTime localDT = LocalDateTime.now();
System.out.println(DateTimeFormatter.ofPattern("dd/MM/yyyy kk:mm:ss").format(localDT));
                    

And the result is (may vary):

04/09/2019 23:22:33

Parse String to Date/Time

You can parse a String into a Date/Time instance using the parse() method

DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss.SSSZ");
ZonedDateTime zdt = ZonedDateTime.from(fmt.parse("25-12-2018 18:20:45.345+0800"));
System.out.println(zdt);
                    

2018-12-25T18:20:45.345+08:00

Which date/time pattern we can use to format/parse?

Date and Time Patterns

Date and time formats are specified by date and time pattern strings. Refer to table below for some of the common date and time patterns used in DateTimeFormatter.

Symbol  Meaning Presentation  Examples
yYear of era year 2018; 18
MMonth of year number/text 07; 7; July; Jul   
dDay of month number 10
EDay of week text Tuesday; Tue; T 
aAm/PM of day text PM
HHour in day (0-23) number 0
hclock hour of am/pm (1-12) number 12
mMinute of hour number 30
sSecond of minute number 55
SMillisecond (fraction of second)    number 978

And some that we might not use that often:

Symbol  Meaning Presentation  Examples
GEra text AD; Anno Domini; A
YWeek based year year 1998; 98
LMonth of year number/text 09; 9
wWeek of week based year    number 27
WWeek of month number 2
DDay of year number 189
FDay of week in month number 2
kClock hour of day (1-24) number 24
KHour of am/pm (0-11) number 0
zTime zone name zone-name Pacific Standard Time; PST
ZZone-offset offset-Z +0000; -0800; -08:00 
xzone-offset offset-x +0000; -08; -0830; -08:30; -083015; -08:30:15 

Use ofPattern() method to get the format based on the pattern. For full format pattern, please check DateTimeFormatter documentation.

Following table showing some Java DateTimeFormatter date/time pattern with example. Current date in my laptop is 4 September 2019, 1 AM, Singapore Time (result may vary):

Date and Time Pattern Result
"dd/MM/yy"04/09/19
"dd MMM yyyy"04 Sep 2019
"yyyy-MM-dd"2019-09-04
"dd-MM-yyyy h:mm a"04-09-2019 1:45 AM
"dd-MM-yyyy hh:mm a, zzzz"04-09-2019 01:45 AM, Singapore Time
"dd-MM-yyyy HH:mm:ss"04-09-2019 01:45:48
"yyyy-MM-dd HH:mm:ss.SSS"2019-09-04 01:45:48.616
"yyyy-MM-dd HH:mm:ss.SSSZ"2019-09-04 01:45:48.616+0800
"EEEE, dd MMMM yyyy HH:mm:ss.SSSZ" Wednesday, 04 September 2019 01:45:48.616+0800 
"yyMMddHHmmssSSS"190904014548616

And following are samples in different Date/Time classes (which implements TemporalAccessor):

DateTimeFormatterFormatExample.java
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class DateTimeFormatterFormatExample {
    
    static void print(String type, String result) {
        System.out.printf("%s: %s\n", type, result);
    }
    
    public static void main(String[] args) {
        // LocalDate
        DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("dd MMM yyyy");
        print("LocalDate", formatter1.format(LocalDate.now()));

        // LocalDateTime
        DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("dd/MM/yyyy hh:mm:ss a");
        print("LocalDateTime", formatter2.format(LocalDateTime.now()));

        // LocalTime
        DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("hh:mm:ss.SSS a");
        print("LocalTime", formatter3.format(LocalTime.now()));
        
        // OffsetDateTime
        DateTimeFormatter formatter4 = DateTimeFormatter.ofPattern("MM/dd/yyyy 'at' hh:mm a");
        print("OffsetDateTime", formatter4.format(OffsetDateTime.now()));
        
        // OffsetTime
        DateTimeFormatter formatter5 = DateTimeFormatter.ofPattern("hh:mm:ss a xx");
        print("OffsetTime", formatter5.format(OffsetTime.now()));
        
        // ZonedDateTime
        DateTimeFormatter formatter6 = DateTimeFormatter.ofPattern("MM/dd/yyyy 'at' hh:mm a z");
        print("ZonedDateTime", formatter6.format(ZonedDateTime.now()));
    }
}
                    

LocalDate: 04 Sep 2019
LocalDateTime: 04/09/2019 01:40:51 AM
LocalTime: 01:40:51.161 AM
OffsetDateTime: 09/04/2019 at 01:40 AM
OffsetTime: 01:40:51 AM +0800
ZonedDateTime: 09/04/2019 at 01:40 AM SGT

Conclusion

The DateTimeFormatter class is used to both parse and format dates according to specified Date and Time Patterns. Use parse(...) method to convert from String to Date/Time classes, use format(...) method to convert from Date/Time into String.

If you not using Java 8 (and above), you can look at SimpleDateFormat.