Java provides an extensive API for handling date and time. In this article, we'll use Java's DateTimeFormatter to format dates -
Before formatting dates, you'll have to know How to Get the Current Date and Time in Java.
Date and time format specifiers are used for constructing patterns to represent data in a format we'd like to present it in.
In the real world, some date or time components are often represented in more than one way. When it comes to time and date format specifiers in Java, those components have two or more representations too - sometimes it is handy to use a short version, while longer versions are more concise and official.
Java 8 overhauled the Date/Time API with thread-safe classes that replaced the old and clunky
This also introduced us to the
DateTimeFormatter class, as opposed to the
SimpleDateFormat from the old API.
It's worth noting that
LocalTime store information about only dates and times respectively, while a
LocalDateTime holds information about both the date and time in a single object.
There are two ways of instantiating a
Writing a pattern:
DateTimeFormatter formatter = DateTimeFormatter .ofPattern("EEE, MMM dd. yyyy.");
Using a formatter:
DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME;
Using a static method:
1. DateTimeFormatter.ofLocalizedDate(FormatStyle dateStyle)
2. DateTimeFormatter.ofLocalizedTime(FormatStyle timeStyle)
3. DateTimeFormatter.ofLocalizedDateTime(FormatStyle datetimeStyle)
4. DateTimeFormatter.ofLocalizedDateTime(FormatStyle dateStyle, FormatStyle timeStyle)
For example, we could set up a
DateTimeFormatter formatter = DateTimeFormatter .ofLocalizedTime(FormatStyle.SHORT);
Note that each one of them has a mandatory argument.
FormatStyle is a built-in enum that provides a few values -
How the available enum patterns look when applied to a
ZonedDateTime object is shown in the following table:
|FormatStyle||Description||Date style||Time style||Date and time style|
|FULL||Highly detailed||Thursday, August 13, 2020||12:43:00 AM Central European Summer Time||Thursday, August 13, 2020 at 12:43:48 AM Central European Summer Time|
|LONG||Contains most of the details||August 13, 2020||12:45:27 AM CEST||August 13, 2020 at 12:44:40 AM CEST|
|MEDIUM||Some details included||Aug 13, 2020||12:45:49 AM||Aug 13, 2020, 12:46:29 AM|
|SHORT||Typically numeric and shortest possible||8/13/20||12:47 AM||8/13/20, 12:47 AM|
In the following code examples, we'll show how to get some of the predefined formatters to do the job for us, as well as making our own. It takes just a few lines of code:
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM); LocalTime time = LocalTime.now(); System.out.println(time.format(formatter));
The resulting output is:
Yet, we should be careful when using predefined formatters. In this case, we can't use
FormatStyle.FULL, because they also yield some time zone information which generally is not stored in
Let's see how it looks when we make our own pattern:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss a"); LocalTime time = LocalTime.now(); System.out.println(time.format(formatter));
Of course, you're free to fiddle around with the pattern.
All the classes supported by
DateTimeFormatter have a
format(DateTimeFormatter f) method, so the process of applying pattern is fairly simple:
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL); LocalDate d = LocalDate.now(); System.out.println(d.format(formatter));
This piece of code yields:
Thursday, August 13, 2020
LocalDateTime is done in the same fashion:
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG, FormatStyle.MEDIUM); LocalDateTime dateTime = LocalDateTime.now(); System.out.println(dateTime.format(formatter));
The resulting output is:
August 13, 2020, 5:29:28 AM
Custom patterns are created in the similar matter:
DateTimeFormatter formatter = DateTimeFormatter .ofPattern("eee, MMM dd. yyyy.\nHH:mm:ss a"); LocalDateTime dt = LocalDateTime.now(); System.out.println(dt.format(formatter));
This piece of code yields:
Tue, Aug 25. 2020. 11:05:20 AM
This time we can casually use the predefined formatter for full output:
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL); ZonedDateTime dateTime = ZonedDateTime.now(); System.out.println(dateTime.format(formatter));
This piece of code outputs:
Thursday, August 13, 2020 at 5:32:49 AM Central European Summer Time
When it comes to creating our own patterns for
ZonedDateTime, we have all the freedom to use whichever specifier we'd like:
DateTimeFormatter formatter = DateTimeFormatter .ofPattern("eee, MMM dd. yyyy.\nHH:mm:ss a - zzzz"); ZonedDateTime dateTime = ZonedDateTime.now(); System.out.println(dateTime.format(formatter));
Tue, Aug 25. 2020. 11:09:27 AM - Central European Summer Time
Format specifiers for
DateTimeFormatter slightly differ from the ones for
SimpleDateFormat. If you're used to working with
SimpleDateFormat, you'll have to adjust some habits by a tiny bit:
|Character||Date or time component||Content type||Example|
|M||Month in year||Number/Text||August;Aug;08|
|w||Week in year||Number||21|
|W||Week in month||Number||2|
|d||Day in month||Number||07;15|
|D||Day in year||Number||176|
|Q/q||Quarter of the year||Number/Text||2:Q2:2nd quarter|
|F|| Day of week in month
(e.g. second Tuesday this month)
|E||Day name in week||Text||Monday;Mon;M|
|e/c||Localized day in week||Number/Text||Monday;Mon;M;1;01|
|u|| Day number of week
(Monday = 1)
|h||Hour in am/pm (1-12)||Number||12|
|H||Hour in day (0-23)||Number||0|
|k||Hour in day (1-24)||Number||24|
|K||Hour in am/pm (0-11)||Number||0|
|m||Minute in hour||Number||43|
|s||Second in minute||Number||58|
|S||Fraction of second||Fraction||965|
|A||Mili of the day||Number||1234|
|n||Nano of second||Number||566787434|
|N||Nano of day||Number||56678743400|
|z||Time zone name||Zone name||Pacific Standard Time; PST|
|V||Time zone ID||Zone ID||America/Los_Angeles; Z; -08:30|
|v||Time zone name||Zone name||Pacific Time; PT0|
|G||Era designator||Text||AD;Anno Domini;A|
- Text - If less than 4 pattern characters are used, component is presented in the short form. Exactly 4 pattern characters will use full form, and exactly 5 will use the narrow form.
- Number - The number of pattern characters is the minimum number of digits. If that number is bigger than the number of digits we actually need to represent a number, then the number is prefixed with corresponding amount of zeros.
Fcan only have one occurence, while
scan have two occurences. Only
Dcan be used up to three times.
- Number/Text - If 3 or more pattern characters are used, the component is presented in textual form; otherwise in number.
- Fraction - Possible character count is between 1 and 9. If less than 9 of them is stated, value is truncated with only the most significant digits being output.
- Year - If the number of pattern characters is 2, the year is truncated to 2 rightmost digits, otherwise it is interpreted as a number.
- Zone ID - If 2 pattern characters are used, zone ID is output; otherwise the exception is thrown.
- Zone name - If the pattern character is
zthe output is the daylight savings aware zone name. If there is insufficient information to determine whether DST applies, the name ignoring Daylight Savings time will be used. If the count of characters is 1, 2 or 3, then the short name is output; if 4 the full name is output. Five or more characters throw an exception. As for the character
v, DST is ignored. If 1 pattern character is used, then the short name is output; if 4 are used, the output is full name. Any other number of characters throw an exception.
In this article, we've showcased how to format a
ZonedDateTime using Java's