Java: Format Dates with SimpleDateFormat

Introduction

Java provides an extensive API for handling date and time. In this article we'll use Java's SimpleDateFormat to format dates.

Before formatting dates, you'll have to know How to Get the Current Date and Time in Java.

Format Specifiers

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.

SimpleDateFormat

SimpleDateFormat only works with Date objects and . In Java 8, several other classes are added to replace the existing date and time API, so it is not unusual to stumble upon deprecated constructors and methods when handling Date objects.

Creating a SimpleDateFormat object is fairly easy. The constructor accepts a string pattern:

SimpleDateFormat formatter = new SimpleDateFormat("EEE, MMM dd. yyyy.");

It is worth mentioning that if we call the constructor with no arguments, a formatter object will be made with default pattern of:

MM/dd/yy, H:mm aa

If we change our mind about the pattern later, we can always apply another one to an object that we have previously created, and the old one will be overriden:

formatter.applyPattern("'date': yyyy.MM.dd -- 'time': H:mm:ss");

Note: In this pattern, we wanted some words to be interpreted literally - so we escaped them with single quotes.

For brevity's sake, we've put the Formatting Rules at the end of the article if you're not familiar with them.

Formatting System.currentTimeMillis()

Formatting the number of miliseconds passed since the UNIX epoch, namely January 1, 1970, 00:00:00 GMT, is fairly simple:

SimpleDateFormat formatter = new SimpleDateFormat("EEE, MMM dd. yyyy. -- H:mm aa");

String formatted = formatter.format(System.currentTimeMillis());
System.out.println(formatted);

Running this piece of code yields:

Tue, Aug 11. 2020. -- 4:48 AM

Internally, the long value is converted into a Date.

Formatting java.util.Date

Formatting a Date is essentially the same, though, we supply a Date instance ourselves:

SimpleDateFormat formatter = new SimpleDateFormat("EEE, MMM dd. yyyy. -- H:mm aa");

Date date = new Date();
String formatted = formatter.format(date);
System.out.println(formatted);

The resulting output is:

Tue, Aug 11. 2020. -- 4:52 AM

Formatting java.util.Calendar

Using a Calendar makes it easier to customize and play around with custom dates. If some important timestamp requires an emphasis, it's easy to do with a Calendar:

SimpleDateFormat formatter = new SimpleDateFormat("EEE, MMM dd. yyyy. -- H:mm aa");

Calendar calendar = Calendar.getInstance();
calendar.set(1969, Calendar.AUGUST, 15, 17, 35, 27);

# SimpleDateFormat works with Dates
Date date = calendar.getTime();

String formatted = formatter.format(date);
System.out.println(formatted);

The resulting output is:

Fri, Aug 15. 1969. -- 17:35 PM

Formatting Rules

For clarity's sake, if you're not already familiar with the formatting rules/patterns used in the article, here's a list of the most notably used format specifiers:

Character Date or time component Content type Example
Y/y Year Year 1969;69
M Month in year Month 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
F Day of week in month
(e.g. second Tuesday this month)
Number 2;3
E Day name in week Text Monday;Mon
u Day number of week
(Monday = 1)
Number 1
a Am/pm marker Text PM;AM
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 Milisecond in second Number 965
z Time zone Time zone CEST;GMT-08:00
G Era designator Text AD

Each content type follows certain rules, mainly regarding the number of pattern characters used in the formatter pattern:

  • Year - If the formatter's Calendar is Gregorian and the number of pattern characters is 2, the year is truncated to 2 rightmost digits, otherwise it is interpreted as a number. In other calendars, calendar specific forms are applied.
  • Month - If the number of pattern characters is 3 or more, the month is shown as text; otherwise it's show as a number. There are short and full textual forms available - if the number of pattern characters is 4 or more, the full form is shown; otherwise the short one is shown.
  • 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.
  • Text - If the number of pattern characters is 4 or more, the full form is used; otherwise a short or abbreviated form is used, if available.
  • Time zone - They are shown as text if they have names. There are short and full form available - if the number of pattern characters is 4 or more, the full form is shown; otherwise the short one is shown. Some time zones do not have names, and they can be shown in various different forms of which one is e.g. the GMT offset value.

Here are some examples of patterns and the results they produce:

Date and time pattern Result
"EEEE, MMM dd. yyyy. -- H:mm aa zzzz" Friday, Aug 15. 1969. -- 17:35 PM Central European Standard Time
"EEE, MMM dd. yyyy. -- H:mm aa zz" Fri, Aug 15. 1969. -- 17:35 PM CET
"MMMM yyyy. GGGG" September 0200. AD
"MMM yyy. GG" Sep 200. AD
"MM-dd-yyyy HH:mm:ss:SSSS" 09-15-2020 17:35:27:0953

Conclusion

In this article, we've covered the SimpleDateFormat class and how we can use it to format dates.

We've formatted the current time (in milliseconds) since the start of UNIX time, a regular Date object and a Calendar object.

Finally, we've covered the formatting specifiers and formatting rules applied to the SimpleDateFormat results.

Author image
Belgrade