Tuesday, September 21, 2021

10 Examples to DateTimeFormatter in Java 8 to Parse, Format LocalDate and LocalTime

Parsing and formatting dates are other essential topics while working with date and time in Java. Even though the old Date API had the SimpleDateFormat and DateFormat class to support the formatting of date and parsing texts, they were not simple, or should I say there were just simple in writing the wrong code. You might know that SimpleDateFormat was not thread-safe and quite heavy to be used as a local variable. Thankfully, this has been sorted now with a new LocalDateTime class and DateTimeFormatter class, which has several inbuilt formats.

For Example, BASIC_ISO_DATE format, which prints dates in yyyyMMdd format, like 20160616, and ISO_DATE which prints dates as yyyy-MM-dd, like 2016-06-16. It has several useful formats to represent popular date formats around the world, like the date format used in the USA is different from than date format used in the UK and India.

Americans write the month before the day, like MM-dd-YY while British writes day, and the same British date format is also popular in India, like dd-MM-YYYY format.

The same date, 16th June 2016, will be written as 06-16-2016 in the United States and 16-06-2016 in Indian and England. Btw, that's not the end of it; there are several other Date formats that are popular around the world as a Japanese write year first, e.g. yyyy-MM-dd or shortened one yy-MM-dd.

The built-in formats which can be used for both parsing text into a date and formatting date into text can be used to cover most of these popular date formats around the world. It also allows you to specify your own custom date format.

The actual formatting and parsing work is done by the format() and parse() method of LocalDateTime class. This is a significant change in API, remember in the old Date API, DateFormat class does both like it specifies the format and also provides parse() and format() method to carry out parsing and formatting. You can further read The Complete Java MasterClass to learn more about the new Date-Time API of Java 8.





10 Examples to Parse and Format Date in Java 8

This is an example-driven article, where you will see lots of how to format a date in Java. I also provide a little bit of commentary around the example to highlight essential details, e.g. you should be using "m" and not "M" while specifying formatting instruction for a month.

Well, the good thing about the new Date and Time API is that it has kept the formatting instruction the same as the old API, so you don't need to learn it again.

The formatting instruction "yyyy-MM-dd" will produce 2016-06-16 with both new (LocalDateTime and DateTimeFormatter) and old Date and time API ((Date and SimpleDateFormat) in Java.

We'll first see examples of formatting dates into various date formats popular around the world, and then we'll learn how to parse the text to date by using the parse() method.


1. 1. Formatting in ISO Format

You can format a date into ISO date format, which is nothing but the yyyy-MM-dd format, i.e. it will print the current date as 2016-06-16, as shown in the following example.

String isoDate = now.format(DateTimeFormatter.ISO_DATE);
System.out.println("ISO date format: " + isoDate);

Output
ISO date format: 2016-06-16

This is an inbuilt formatter available in DateTimeFormatter class, it's static as well, so just access it like we have done in this example. No need to specify any pattern.



1.2. Formatting LocalDateTime into BASIC_ISO_FORMAT

This is a close cousin of the previous example, the BASIC_ISO_FORMAT is nothing but yyyyMMdd format, like 20160616, and this is also a built-in format, so you don't need to do anything, you can use call the format() method of LocalDateTime class and pass this formatter as shown in the following example:

String basicIsoDate = now.format(DateTimeFormatter.BASIC_ISO_DATE);
System.out.println("Basic ISO date format: " + basicIsoDate);

Output
Basic ISO date format: 20160616



1.3. Formatting Date in dd-MM-yyyy Format

The new Date and Time API not just provide a built-in DateTimeFormatter but also allow you to create a custom one by specifying the pattern you want. In this example, we are creating a custom DateTimeFormatter pattern to show dates in an Indian date format, like dd-MM-yyyy (16-06-2016). This is also the British date format, popular in England and some parts of the UK.

String indianDateFormat = now.format(DateTimeFormatter.ofPattern("dd-MM-yyyy"));
System.out.println("formatting in Indian date format: " + indianDateFormat);

Output
formatting in Indian date format: 16-06-2016



1.4. How to format Date in Americal Date format

Well, the United States of America uses a different date format Britain. They put Month before Day like Americans uses MM-dd-yyyy format. You can again pass our USA date pattern to DateTimeFormatter.ofPattern() method and retrieve a formatter to format date in American format as shown below:

DateTimeFormatter americanDateFormat = DateTimeFormatter.ofPattern("MM-dd-yyyy");
String americanDate = now.format(americanDateFormat);
System.out.println("USA date format : " + americanDate);

Output
USA date format: 06-16-2016

The bottom line is as long as you understand the Date and Time formatting instruction, you can define any pattern to formate date.

Just make sure the pattern is valid and applicable to the LocalDateTime class like using a pattern that contains timezone information with LocalDateTime will not work and throw the following error at compile time:

Exception in thread "main" 
java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: OffsetSeconds
at java.time.LocalDate.get0(LocalDate.java:680)
at java.time.LocalDate.getLong(LocalDate.java:659)
at java.time.LocalDateTime.getLong(LocalDateTime.java:720)
at java.time.format.DateTimePrintContext.getValue(DateTimePrintContext.java:298)
at java.time.format.DateTimeFormatterBuilder$OffsetIdPrinterParser.format
(DateTimeFormatterBuilder.java:3338)
at java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.format
(DateTimeFormatterBuilder.java:2182)
at java.time.format.DateTimeFormatter.formatTo(DateTimeFormatter.java:1744)
at java.time.format.DateTimeFormatter.format(DateTimeFormatter.java:1718)
at java.time.LocalDateTime.format(LocalDateTime.java:1746)
at test.Test.main(Test.java:65

The reason is apparent, there is no timezone information present in LocalDateTime. If you want to print data with timezone, then you should first convert LocalDateTimet to ZonedDateTime and then format it.

Don't worry, we'll see an example of formatting date with timezone later in this article. If you want to learn more, you can also see the What's New in Java 8 course on Pluralsight.

How to format Date in Americal Date format




1.5. How to print date in Japanese DateFormat

Japanese use a different date format than the UK and USA; they put the year first followed by month and day. You can define both long and short date formats for Japan using patterns "yyyy-MM-dd" and "yy-MM-dd" as shown in the below example

DateTimeFormatter japan = DateTimeFormatter.ofPattern("yy-MM-dd");
String japanese = now.format(japan);
System.out.println("Date in Japan dateformat : " + japanese);

Output
Date in Japan date format: 16-06-16



1.6. Formatting LocalDateTime in ISO date time format

So far, we have only formatted LocalDateTime to date String, but since it doesn't contain time information, you can also format it into a String containing both date and time using DateTimeFormatter.ISO_DATE_TIME formatter, as shown below:

String isoDateTime = now.format(DateTimeFormatter.ISO_DATE_TIME);
System.out.println("Date in ISO date time format: " + isoDateTime);

Output
Date in ISO date time format: 2016-06-16T12:21:18.311



1.7. How to print Localized Date in Java

The DateTimeFormatter also allows you to create a format to represent a date in a localized format, like in French, German, or any other format. For example, the month of June is called "juin" in French and if you want to print a date, like16. juin 2016, you need to let DatTimeFormatter know that you are interested in the French locale.

You can do this by using the overloaded version of DateTimeFormatter.ofPattern(pattern, local) method, which also accepts a Local as shown in the following example:

DateTimeFormatter french = DateTimeFormatter.ofPattern("d. MMMM yyyy",new Locale("fr"));
String frenchDate = now.format(French);
System.out.println("Date in french format: " + frenchDate);

Output
Date in french format: 16. juin 2016

You can see that Java has printed date in french format, "Jun" is written as "Juin," good stuff? No?





1.8. Formatting Date in Short Deutsche date/time formatting (06.16.16 12:07)

Here is one more example of the formatting date in Java 8 as per locale. This time we are printing the date in short german date-time format, i.e. 06.16.116 12:07. We are using the same approach as the previous example with the only change that instead of passing our pattern, we are leveraging the built-in ofLocalizedDateTime() method to create a localized date format.

DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT)
.withLocale(new Locale("de"));
String germanDateTime = now.format(formatter);
System.out.println("Date in short german format : " + germanDateTime);

Output
Date in short german format: 16.06.16 12:21

You use this approach to print dates in any other locale, as well.


1.9. How to format time in Java 8

So far, we have seen an example for formatting Date and DateTime, and now is a time to print formatted time in Java 8. Nothing changes except the DateTimeFormatter instance, this time, we'll use the DateTimeFormatter.ISO_TIME format, which prints time in HH:mm:ss:SSS format.

Here "s" is for a second, and "S" is for a millisecond. See the DateTimeFormat class for a full list of formatting instructions you can use to generate a pattern for formatting and parsing.

String isoTime = now.format(DateTimeFormatter.ISO_TIME);
System.out.println("time in ISO TIME format : " + isoTime);

Output
time in ISO TIME format: 12:21:18.311



1.10. Printing date in the long format in Java

Sometimes we need to print the date in an extended format, e.g. 16th June 2016. You can do so by using pattern dd-MMM-yyyy, the three M patterns will print the Month in three letters, e.g. "Jan", "Feb" or "Jun".

If you want the full name of the month, just use the "MMMM" pattern. The rest of the process is the same as the earlier example, you pass this pattern to the static factory method ofPattern(), which returns a corresponding DateTimeFormatter instance, which is used by LocalDateTime to convert a date in long format.

String longFormat = now.format(DateTimeFormatter.ofPattern("dd-MMM-yyyy"));
System.out.println("date in long format : " + longFormat);

Output
date in long format: 16-Jun-2016

If you don't want a dash in between, just remove the dash and introduce space. See Java SE 8 for Really Impatient by Cay S. Horstmann to learn more. One of the best books to learn Java 8.

How to print date with timezone in Java



2. How to print date with timezone in Java

Well, in order to format a DateTime with timezone, you need a ZonedDateTime object, LocalDateTime is not sufficient as it doesn't contain timezone information. You can convert LocalDateTime to ZonedDateTime by providing ZoneId of any timezone you want like "Europe/London" or "America/New_York". 

Once you an object of ZonedDateTime, just use the builtin ISO_ZONED_DATE_TIME formatter to print date with timezone in Java as done in the following example:

ZonedDateTime dateWithTimeZone = ZonedDateTime.of(now, ZoneId.of("Europe/London"));
String withTimeZone = dateWithTimeZone.format(DateTimeFormatter.ISO_ZONED_DATE_TIME);
System.out.println("date time with timezone : " + withTimeZone);

Output
date time with timezone : 2016-06-16T12:21:18.311+01:00[Europe/London]

If you don't follow the advice and try to format a LocalDatetime instance with ISO_ZONED_DATE_TIME ('2011-12-03T10:15:30Z') or RFC_1123_DATE_TIME (Tue, 3 Jun 2008 11:05:30 GMT'), you will get the following error:

Exception in thread "main" java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: OffsetSeconds

which is obvious, because you don't have time zone-related data.


3. How to parse the text to LocalDateTime in Java? Example

Now that you know about how to format the date in Java, in which we create a formatted String from the LocalDateTime object, it's time to learn the other way, i.e. converting formatted String to Date in Java 8

All the knowledge you acquire about the date and time patterns while formatting is equally applicable here because you still need to create DateTimeFormatter of the pattern your date is, without that you cannot parse the text.

Another worth noting point is that all three key classes, like LocalDate, LocalTime, and LocalDateTime, have to parse() method, and they are overloaded two. The parse() method of LocalDate will parse the String by using ISO_LOCAL_DATE, like "2016-06-16" and parse(DateTimeFormatter) will parse according to the pattern specified in that class. If the text is not valid as per the pattern, then ParseException will be thrown.

Similarly, LocalTime also has a parse() method to parse text into ISO_LOCAL_TIME format, and LocalDateTime also has a parse method convert String of ISO_LOCAL_DATETIME format.

Let's a couple of examples of parsing Date String to LocalDate in Java 8:

LocalDate fromIsoDate = LocalDate.parse("2015-02-23");
LocalDate fromCustomPattern = LocalDate.parse("20-03-2017", 
                             DateTimeFormatter.ofPattern("dd-MM-yyyy"));
LocalDate invalidDate = LocalDate.parse("16-02-2018");

The first two is fine becuase the formatted String is per the pattern specified by DateTimeFormatter but the last one is invalid because the date is in the dd-MM-yyyy format as opposed to YYYY-MM-dd of ISO_DATE format, hence it will throw the following error:

Exception in thread "main" 
java.time.format.DateTimeParseException: Text '16-02-2018' could not be parsed at index 0
at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1947) 
at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1947)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1849)
at java.time.LocalDate.parse(LocalDate.java:400)
at java.time.LocalDate.parse(LocalDate.java:385)


Similarly, you can also parse text to LocalTime instance as shown below:

LocalTime fromIsoTime = LocalTime.parse("12:07:43.048");
LocalTime fromPattern = LocalTime.parse("11:06:32", 
                                      DateTimeFormatter.ofPattern("HH:mm:ss"));

and you can do the same with LocalDateTime or ZonedDateTime, if String contains the timezone information, you can convert it to ZonedDateTime instance as well, as shown in the following example:

LocalDateTime fromIsoDateTime = LocalDateTime.parse("2016-06-16T13:12:38.954");
ZonedDateTime fromIsoZonedDateTime 
  = ZonedDateTime.parse("2016-06-16T13:12:38.954+01:00[Europe/London]");

And here is the complete Java program to show you how to use LocalDateTime and DateTimeFormatter to format and parse dates in Java 8. If you want to learn more about Date-Time API and Java 8 in general, you can also check out The Complete Java MasterClass course on Udemy. One of the most up-to-date Java courses which are also recently updated for Java 11.

10 Examples of format and parse Dates in Java 8 using LocalDateTime and DateTimeFormatter



4. Java Program to format and parse Dates in JDK 8

Here is the complete sample program to demonstrate all the ways to format and parse date and time in JDK 8. 

package test;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Month;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Locale;

/**
 * Java Program to demonstrate how to use LocalDate, LocalTime, and
 * LocalDateTime in Java 8.
 */
public class Test {

  public static void main(String[] args) {

    // Formatting dates in Java 8
    LocalDateTime now = LocalDateTime.now();

    
    // Example 1 - print date as 2016-06-16 (yyyy-MM-dd)
    String isoDate = now.format(DateTimeFormatter.ISO_DATE);
    System.out.println("ISO date format: " + isoDate);

    
    // Example 2 - print date as 20160616 (yyyyMMdd)
    String basicIsoDate = now.format(DateTimeFormatter.BASIC_ISO_DATE);
    System.out.println("Basic ISO date format: " + basicIsoDate);

    
    // Example 3 - formatting date in British or Indian date format dd-MM-yyyy
    String indianDateFormat = now.format(DateTimeFormatter
        .ofPattern("dd-MM-yyyy"));
    System.out.println("formatting in Indian date format: " + indianDateFormat);

    
    // Example 4 - formatting date in USA date format (06-16-2016)
    DateTimeFormatter americanDateFormat = DateTimeFormatter
        .ofPattern("MM-dd-yyyy");
    String americanDate = now.format(americanDateFormat);
    System.out.println("USA date format : " + americanDate);

    
    // Example 5 - formatting in Japanese date format (16-06-16)
    DateTimeFormatter japan = DateTimeFormatter.ofPattern("yy-MM-dd");
    String japanese = now.format(japan);
    System.out.println("Date in Japan dateformat : " + japanese);

    
    // Example 6 - format in ISO date time format
    String isoDateTime = now.format(DateTimeFormatter.ISO_DATE_TIME);
    System.out.println("Date in ISO date time format: " + isoDateTime);

    
    // Example 7 - french date formatting 16. juin 2016
    DateTimeFormatter french = DateTimeFormatter.ofPattern("d. MMMM yyyy",
        new Locale("fr"));
    String frenchDate = now.format(french);
    System.out.println("Date in french format: " + frenchDate);

    
    // Example 8 - using short german date/time formatting (06.16.16 12:07)
    DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(
        FormatStyle.SHORT).withLocale(new Locale("de"));
    String germanDateTime = now.format(formatter);
    System.out.println("Date in short german format : " + germanDateTime);

    
    // Example 9 - formatting time in ISO_TIME format
    String isoTime = now.format(DateTimeFormatter.ISO_TIME);
    System.out.println("time in ISO TIME format : " + isoTime);

    
    // Example 10 - printing date in long format e.g. 16th June 2016
    String longFormat = now.format(DateTimeFormatter.ofPattern("dd-MMM-yyyy"));
    System.out.println("date in long format : " + longFormat);

    
    // Example 11 - formatting date with timezone
    ZonedDateTime dateWithTimeZone = ZonedDateTime.of(now,
        ZoneId.of("Europe/London"));
    String withTimeZone = dateWithTimeZone
        .format(DateTimeFormatter.ISO_ZONED_DATE_TIME);
    System.out.println("date time with timezone : " + withTimeZone);

    
    // Parsing text to Date in Java 8
    LocalDate fromIsoDate = LocalDate.parse("2015-02-23");
    LocalDate fromCustomPattern = LocalDate.parse("20-03-2017",
        DateTimeFormatter.ofPattern("dd-MM-yyyy"));
    // LocalDate invalidDate = LocalDate.parse("16-02-2018");

    
    // parsing text to LocalTime in Java 8
    LocalTime fromIsoTime = LocalTime.parse("12:07:43.048");
    LocalTime fromPattern = LocalTime.parse("11:06:32",
        DateTimeFormatter.ofPattern("HH:mm:ss"));

    
    // converting String LocalDateTime and ZonedDateTime in Java 8
    LocalDateTime fromIsoDateTime = LocalDateTime
        .parse("2016-06-16T13:12:38.954");
    ZonedDateTime fromIsoZonedDateTime = ZonedDateTime
        .parse("2016-06-16T13:12:38.954+01:00[Europe/London]");

  }

}

Output
ISO date format: 2016-06-16
Basic ISO date format: 20160616
formatting in Indian date format: 16-06-2016
USA date format : 06-16-2016
Date in Japan dateformat : 16-06-16
Date in ISO date time format: 2016-06-16T13:14:40.948
Date in french format: 16. juin 2016
Date in short german format : 16.06.16 13:14
time in ISO TIME format : 13:14:40.948
date in long format : 16-Jun-2016
date time with timezone : 2016-06-16T13:14:40.948+01:00[Europe/London]


That's all about how to parse and format the date and time in Java. We've seen lots of examples to format LocalDateTime to various popular date-time formats around the world, like the USA date format "yyyy-MM-dd" and the UK date format "dd-MM-yyyy" which is also popular in India. Wherever possible, use the built-in formatter from the DateTimeFormatter class. You also don't need to be worried about thread safety because both LocalDateTime and DateTimeFormatter are immutable in Java 8.



Related Java 8 Tutorials
If you are interested in learning more about the new features of Java 8, here are my earlier articles covering some of the important concepts of Java 8:
  • 5 Free Courses to learn Java 8 and Java 9 (courses)
  • 5 Books to Learn Java 8 from Scratch (books)
  • How to join String in Java 8 (example)
  • How to use filter() method in Java 8 (tutorial)
  • How to format/parse the date with LocalDateTime in Java 8? (tutorial)
  • How to use Stream class in Java 8 (tutorial)
  • How to convert List to Map in Java 8 (solution)
  • 20 Examples of Date and Time in Java 8 (tutorial)
  • How to use peek() method in Java 8 (example)
  • How to sort the map by keys in Java 8? (example)
  • How to sort the may by values in Java 8? (example)
  • 10 examples of Optional in Java 8? (example)
  • Difference between abstract class and interface in Java 8? (answer)
  • Top 5 Online Courses to Master Java 8 Concepts (courses)

Thanks for reading this article so far. If you like this comprehensive Java Date formatting and parsing tutorial, then please share it with your friends and colleagues. If you have any questions or feedback, then please drop a comment.

P. S.: If you just want to learn more about new features in Java 8, then please see this list of Java 8 to Java 13 courses. It has online courses to learn all the important features of Java 8, like lambda expressions, streams, functional interfaces, Optional, new Date-Time API, and other miscellaneous changes.

No comments:

Post a Comment

Feel free to comment, ask questions if you have any doubt.