1. Overview

String.format, System.out.printf and System.out.format, all use the Formatter class to provide rich formatting functionalities.

In this tutorial, we will look at Java's format rules and examine several format specifiers.

2. General Rules

Let's start with a simple example:

public void basicUsage() {
    String greet = String.format("Hello %s", "John");
    System.out.println(greet);
}

The result is Hello John because the argument John is formatted as String and then replaced with %s.

Now let's break down this example.

Firstly, every formatting method requires a format string and an argument list.

  • String.format is a formatting method.
  • "Hello %s" is a format string.
  • "World" is an argument list of size 1.

A format string can include fixed strings and format specifiers.

  • "Hello " is a fixed string.
  • "%s" is a format specifier.

In essence, we'll be dealing with format specifiers throughout the tutorial.

The format specifier has a syntax depending on the argument type. For example, the character and numeric types have the following syntax:

%[argument_index$][flags][width][.precision]conversion
  • The parts in brackets - like flags and width - are optional.
  • %s only contains the conversion part. it doesn't contain argument_index, flags, width or precision.

There are also format specifiers that don't expect arguments:

  • %n outputs a new line
  • %% outputs the percentage symbol

Now that we have learned the basics, we'll explore different format specifiers for several types.

3. Format Numbers

The format specifier syntax for numbers is:

%[argument_index$][flags][width][.precision]conversion

3.1. Format Integral Numbers

Firstly, we must specify the conversion identifier as d and pass an integer value:

System.out.format("' %d '%n", 12);
' 12 '

%d specifies the conversion and skips argument index, flags, width, and precision.

We can also specify the argument index:

System.out.format("' %1$d '%n", 12);
' 12 '

%1$d specifies d as conversion and 1$ as argument index.

We can reuse an argument by specifying the argument index:

System.out.format("' %1$d %1$d '%n", 12);
' 12 12 '

We can set the width for the string output:

System.out.format("' %10d '%n", 12);
'         12 '

By default, the output is right-justified. Though we can make it left-justified, using '-' flag:

System.out.format("' %-10d '%n", 12);
' 12         '

Or we can make it filled with zeros, using '0' flag:

System.out.format("' %010d '%n", 12);
' 0000000012 '

Let's switch to a bigger number now.

We can put grouping separators, using ',' flag:

System.out.format("' %,d '%n", 12000);
' 12,000 '

Additionally, we can add the plus sign, using '+' flag:

System.out.format("' %+,d '%n", 12000);
' +12,000 '

3.2. Format Floating-Point Numbers

We must first specify the conversion identifier as 'f' and pass a floating-point value:

System.out.format("' %f '%n", 12.567);
' 12.567000 '

The default precision value is 6. Thus if the digit count in the fraction is less than 6, zeros will be appended as in 12.567000.

We can also set the precision:

System.out.format("' %.5f '%n", 12.56789);
' 12.56789 '

%.5f defines precision as 5.

If the precision is less than the digit count in the number's fraction part, the number is rounded:

System.out.format("' %.3f '%n", 12.56789);
' 12.568 '

Because of the round operation, we have 12.568 instead of 12.567.

We can set the width and alignment for the floating-point numbers:

System.out.format("' %5f '%n", 12.56789);
System.out.format("' %20f '%n", 12.56789);
System.out.format("' %-20f '%n", 12.56789);
System.out.format("' %020f '%n", 12.56789);
' 12.567890 '
'            12.567890 '
' 12.567890            '
' 0000000000012.567890 '

Similar to integers, grouping separator and plus sign can be added using the ',' and '+' flags:

System.out.format("' %,f '%n", 12000.56789);
System.out.format("' %+,f '%n", 12000.56789);
' 12,000.567890 '
' +12,000.567890 '

4. Format Strings

Similar to the numbers, the format specifier syntax for strings is:

%[argument_index$][flags][width][.precision]conversion

We must use the s conversion identifier and pass a value:

System.out.format("' %s '%n", "Hello!");
System.out.format("' %s '%n", 12);
System.out.format("' %s '%n", 12.01);
' Hello! '
' 12 '
' 12.01 '

The output string is generated by the toString method. However, if the argument implements Formattable, the formatTo method is called instead.

If the precision is less than the string length, it truncates the value:

System.out.format("' %.2s '%n", "Hello!");
' He '

In addition to precision, we can set the width and justify the output:

System.out.format("' %10.2s '%n", "Hello!");
System.out.format("' %-10.2s '%n", "Hello!");
'         He '
' He         '

5. Format Date and Time

The format specifier syntax for date and time is:

%[argument_index$][flags][width]conversion

We must always set the conversion either as t or T. They function similarly except T converts the output to uppercase.

Additionally, there are suffixes which decides the final formatting.

5.1. Format Date

Firstly, we can access to different parts of the date:

  • d: outputs the two-digit day of the month
  • m: outputs the two-digit month
  • y: outputs the last two digits of the year
  • Y: outputs the year in four digits
System.out.format("' %tm '%n", date);
System.out.format("' %td '%n", date);
System.out.format("' %ty '%n", date);
System.out.format("' %tY '%n", date);
' 07 '
' 25 '
' 00 '
' 2100 '

We can also retrieve the names of the date elements:

  • A: outputs the full day of the week
  • B: outputs the full month name
System.out.format("' %tA '%n", date);
System.out.format("' %tB '%n", date);
System.out.format("' %TA '%n", date);
' Sunday '
' July '
' SUNDAY '

Lastly, there are some shortcut suffixes:

  • D expands as %1$td/%1$tm/%1$ty
  • F expands as %1$tY-%1$tm-%1$td
  • c expands as %1$ta %1$tb %1$td %1$tT %1$tZ %1$tY
System.out.format("' %tD '%n", date);
System.out.format("' %tF '%n", date);
System.out.format("' %tc '%n", date);
' 07/25/00 '
' 2100-07-25 '
' Sun Jul 25 14:30:40 EET 2100 '

5.2. Format Time

Similar to dates, we can access different parts of the time:

  • H: outputs the hour
  • M: outputs the minute
  • S: outputs the second
  • p: outputs am/pm
System.out.format("' %tH '%n", date);
System.out.format("' %tM '%n", date);
System.out.format("' %tS '%n", date);
System.out.format("' %tp '%n", date);
' 14 '
' 30 '
' 40 '
' pm '

We can also use the shortcut suffixes:

  • r expands as %1$tI:%1$tM:%1$tS %1$Tp
  • R expands as %1$tH:%1$tM
  • T expands as %1$tH:%1$tM:%1$tS
System.out.format("' %tr '%n", date);
System.out.format("' %tR '%n", date);
System.out.format("' %tT '%n", date);
' 02:30:40 PM '
' 14:30 '
' 14:30:40 '

6. Summary

In this tutorial, we've looked at Java's formatting rules which are captured in the Formatter class. These rules are in effect in the most used parts of Java such as String.format and System.out.printf.

Finally, check out the source code for all examples over on Github.