How to Format Dates with SimpleDateFormat

You can format dates in Java using the SimpleDateFormat class, which is part of the java.text package. This class allows you to specify patterns describing the formatting and parsing of date and time objects.

Here’s a step-by-step guide:


Example of Formatting Dates with SimpleDateFormat

package org.kodejava.text;

import java.text.SimpleDateFormat;
import java.util.Date;

public class DateFormatExample {
   public static void main(String[] args) {
      // Create an instance of SimpleDateFormat
      // Specify the desired pattern
      SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");

      // Get the current date
      Date currentDate = new Date();

      // Format the date
      String formattedDate = simpleDateFormat.format(currentDate);

      // Print the result
      System.out.println("Formatted Date: " + formattedDate);
   }
}

Common Patterns for Date and Time Formatting

Here are some of the most commonly used patterns:

Symbol Description Example
y Year 2025
M Month in year 08 or August
d Day of the month 02
h Hour in AM/PM (1-12) 3
H Hour in day (0-23) 15
m Minute in hour 45
s Second in minute 30
S Millisecond 978
E Day of the week Tue
D Day of the year 214
z Time zone PDT
Z Time zone offset -0700

You can mix and match these symbols to create a pattern that suits your needs.


Example with Custom Pattern

SimpleDateFormat dateFormat = new SimpleDateFormat("EEEE, MMM dd, yyyy hh:mm a");
Date date = new Date();
System.out.println("Custom Formatted Date: " + dateFormat.format(date));

Output:

Custom Formatted Date: Saturday, Aug 02, 2025 10:30 AM

Notes:

  1. Thread Safety:
    SimpleDateFormat is not thread-safe. If you need to use it in a multithreaded environment, you should manage synchronization or use java.time.format.DateTimeFormatter, which is thread-safe and introduced in Java 8.

  2. For Java 8 and Later:
    If you’re using Java 8 or later, consider using the new java.time API (DateTimeFormatter) for better clarity and thread safety.

How do I format a number as percentage with fraction digits?

In Java, the NumberFormat class of java.text package can be used to format numbers. For formatting a number as a percentage string with fraction digits, you can use the getPercentInstance() method that returns a percentage format for the current default Locale.

Here is a sample code snippet showing how to format a number as a percentage string with two digits of fractions:

package org.kodejava.text;

import java.text.NumberFormat;

public class FormatPercentage {
    public static void main(String[] args) {
        double number = 0.12345;

        // Get an instance of NumberFormat for percentage
        NumberFormat percentFormat = NumberFormat.getPercentInstance();

        // Set the fraction digits - change this value to control the
        // number of fraction digits.
        percentFormat.setMinimumFractionDigits(2); // set the minimum
        percentFormat.setMaximumFractionDigits(4); // set the maximum

        // Format the number as a percentage
        String formattedPercent = percentFormat.format(number);

        System.out.println("Number as percentage: " + formattedPercent);
    }
}

Output:

Number as percentage: 12.345%

In the above example, 0.12345 will be formatted as 12.35% because we have set the MinimumFractionDigits to 2 which means up to two decimal points will be included in the formatted percentage. If we also set the MaximumFractionDigits it will allow us to have up to four decimal points in the output value, here we have 12.345%.

Note that the actual percentage is calculated by multiplying the number by 100, so 0.12345 becomes 12.345% and then rounded to 12.35% (because of the fraction digits setting, in this case we only set the minimum fraction digits to two decimal points).

We can also use the DecimalFormat class. The DecimalFormat class in Java is used to format decimal numbers. It is a subclass of NumberFormat and you can customize the format of your number using it.

Here’s a simple example of how you can format a number as a percentage string using DecimalFormat:

package org.kodejava.text;

import java.text.DecimalFormat;

public class DecimalFormatPercentDemo {
    public static void main(String[] args) {
        double number = 0.123;

        // Create a new DecimalFormat instance with a percentage pattern
        DecimalFormat df = new DecimalFormat("#%");

        // Set the number of fraction digits 
        df.setMinimumFractionDigits(2);

        // Format the number into a percentage
        String percentage = df.format(number);

        System.out.println(percentage);
    }
}

This program will output 12.30%

The "#%" pattern means that the number should be formatted as a percentage. And df.setMinimumFractionDigits(2); means that the decimal will be formatted to two places.

The DecimalFormat will automatically multiply our value by 100, which is why 0.123 appears as 12.30%.

How do I parse negative number in parentheses?

In financial application negative numbers are often represented in parentheses. In this post we will learn how we can parse or convert the negative number in parentheses to produce the represented number value. To parse text / string to a number we can use the java.text.DecimalFormat class.

Beside number in parentheses, in this example we also parse negative number that use the minus sign with the currency symbol like $. Let’s jump to the code snippet below:

package org.kodejava.text;

import java.text.DecimalFormat;

public class NegativeNumberParse {
    // Pattern for parsing negative number.
    public static final String PATTERN1 = "#,##0.00;(#,##0.00)";
    public static final String PATTERN2 = "$#,##0.00;-$#,##0.00";

    public static void main(String[] args) throws Exception {
        DecimalFormat df = new DecimalFormat(PATTERN1);

        String number1 = "(1000)";
        String number2 = "(1,500.99)";

        System.out.println("number1 = " + df.parse(number1));
        System.out.println("number2 = " + df.parse(number2));

        df = (DecimalFormat) DecimalFormat.getInstance();
        df.applyPattern(PATTERN2);

        String number3 = "-$1000";
        String number4 = "-$1,500.99";

        System.out.println("number3 = " + df.parse(number3));
        System.out.println("number4 = " + df.parse(number4));
    }
}

And here are the results of our code snippet above:

number1 = -1000
number2 = -1500.99
number3 = -1000
number4 = -1500.99

If you need to display or format negative numbers in parentheses you can take a look at the following example How do I display negative number in parentheses?.

How do I display negative number in parentheses?

The code snippet below show us how to display or format negative number in parentheses. We start by defining the number format, the pattern has two parts separated by a semicolon. In the snippet we use the #,##0.00;(#,##0.00) pattern. The pattern after the semicolon will be used to format negative number.

Next we create an instance of DecimalFormat by calling getInstance() method. We apply the format pattern for the formatter object by calling the applyPattern() method of the DecimalFormat instance. To format the number we simply call the format() method and pass the number we are going to format for display or print out.

package org.kodejava.text;

import java.text.DecimalFormat;

public class NegativeNumberFormat {
    // Pattern for formatting negative number.
    public static final String PATTERN1 = "#,##0.00;(#,##0.00)";
    public static final String PATTERN2 = "$#,##0.00;-$#,##0.00";

    public static void main(String[] args) {
        DecimalFormat df = (DecimalFormat) DecimalFormat.getInstance();
        df.applyPattern(PATTERN1);

        // Format using parentheses
        System.out.println("Positive: " + df.format(125));
        System.out.println("Negative: " + df.format(-125));

        // Format using currency symbol and minus sign
        df.applyPattern(PATTERN2);
        System.out.println("Positive: " + df.format(1000));
        System.out.println("Negative: " + df.format(-1000));
    }
}

The result of the code snippet above is:

Positive: 125.00
Negative: (125.00)
Positive: $1,000.00
Negative: -$1,000.00

If you need to parse negative numbers in parentheses to produce the represented number you can see the following example How do I parse negative number in parentheses?.

How do I convert string to Date in GMT timezone?

The following code snippet convert a string representation of a date into a java.util.Date object and the timezone is set to GMT. To parse the string so that the result is in GMT you must set the TimeZone of the DateFormat object into GMT.

package org.kodejava.joda;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class WithTimezoneStringToDate {
    public static void main(String[] args) {
        // Create a DateFormat and set the timezone to GMT.
        DateFormat df = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z");
        df.setTimeZone(TimeZone.getTimeZone("GMT"));

        try {
            // Convert string into Date
            Date today = df.parse("Fri, 29 Oct 2021 00:00:00 GMT+08:00");
            System.out.println("Today = " + df.format(today));
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

The code snippet above print the following output:

Today = Thu, 28 Oct 2021 16:00:00 GMT

How do I get pattern string of a SimpleDateFormat?

To format a java.util.Date object we use the SimpleDateFormat class. To get back the string pattern that were used to format the date we can use the toPattern() method of this class.

package org.kodejava.text;

import java.text.SimpleDateFormat;
import java.util.Date;

public class SimpleDateFormatToPattern {
    public static void main(String[] args) {
        SimpleDateFormat format = new SimpleDateFormat("EEEE, dd/MM/yyyy");

        // Gets a pattern string describing this date format used by the
        // SimpleDateFormat object.
        String pattern = format.toPattern();

        System.out.println("Pattern = " + pattern);
        System.out.println("Date    = " + format.format(new Date()));
    }
}

The result of the program will be as follow:

Pattern = EEEE, dd/MM/yyyy
Date    = Tuesday, 26/10/2021

How do I break a paragraph into sentences?

This example show you how to use the BreakIterator.getSentenceInstance() to breaks a paragraphs into sentences that composes the paragraph. To get the BreakIterator instance we call the getSentenceInstance() factory method and passes a locale information.

In the count(BreakIterator bi, String source) method we iterate the break to extract sentences that composes the paragraph which value is stored in the paragraph variable.

package org.kodejava.text;

import java.text.BreakIterator;
import java.util.Locale;

public class BreakSentenceExample {
    public static void main(String[] args) {
        String paragraph = """
                Line boundary analysis determines where a text \
                string can be broken when line-wrapping. The \
                mechanism correctly handles punctuation and \
                hyphenated words. Actual line breaking needs to \
                also consider the available line width and is \
                handled by higher-level software.
                """;

        BreakIterator iterator = BreakIterator.getSentenceInstance(Locale.US);

        int sentences = count(iterator, paragraph);
        System.out.println("Number of sentences: " + sentences);
    }

    private static int count(BreakIterator bi, String source) {
        int counter = 0;
        bi.setText(source);

        int lastIndex = bi.first();
        while (lastIndex != BreakIterator.DONE) {
            int firstIndex = lastIndex;
            lastIndex = bi.next();

            if (lastIndex != BreakIterator.DONE) {
                String sentence = source.substring(firstIndex, lastIndex);
                System.out.println("sentence = " + sentence);
                counter++;
            }
        }
        return counter;
    }
}

Our program will print the following result on the console screen:

sentence = Line boundary analysis determines where a text string can be broken when line-wrapping. 
sentence = The mechanism correctly handles punctuation and hyphenated words. 
sentence = Actual line breaking needs to also consider the available line width and is handled by higher-level software.

Number of sentences: 3

How do I break a text or sentence into words?

At first, it might look simple. We can just split the text using the String.split(), the word is split using space. But what if a word ends with questions marks (?) or exclamation marks (!) instead? There might be some other rules that we also need to care.

Using the java.text.BreakIterator makes it much simpler. The class’s getWordInstance() factory method creates a BreakIterator instance for words break. Instantiating a BreakIterator and passing a locale information makes the iterator to breaks the text or sentence according the rule of the locale. This is really helpful when we are working with a complex language such as Japanese or Chinese.

Let us see an example of using the BreakIterator below.

package org.kodejava.text;

import java.text.BreakIterator;
import java.util.Locale;

public class BreakIteratorExample {
    public static void main(String[] args) {
        String data = "The quick brown fox jumps over the lazy dog.";
        String search = "dog";

        // Gets an instance of BreakIterator for word break for the
        // given locale. We can instantiate a BreakIterator without
        // specifying the locale. The locale is important when we
        // are working with languages like Japanese or Chinese where
        // the breaks standard may be different compared to English.
        BreakIterator bi = BreakIterator.getWordInstance(Locale.US);

        // Set the text string to be scanned.
        bi.setText(data);

        // Iterates the boundary / breaks
        System.out.println("Iterates each word: ");
        int count = 0;
        int lastIndex = bi.first();
        while (lastIndex != BreakIterator.DONE) {
            int firstIndex = lastIndex;
            lastIndex = bi.next();

            if (lastIndex != BreakIterator.DONE
                    && Character.isLetterOrDigit(data.charAt(firstIndex))) {
                String word = data.substring(firstIndex, lastIndex);
                System.out.printf("'%s' found at (%s, %s)%n",
                        word, firstIndex, lastIndex);

                // Counts how many times the word dog occurs.
                if (word.equalsIgnoreCase(search)) {
                    count++;
                }
            }
        }

        System.out.println("Number of word '" + search + "' found = " + count);
    }
}

Here are the program output:

Iterates each word: 
'The' found at (0, 3)
'quick' found at (4, 9)
'brown' found at (10, 15)
'fox' found at (16, 19)
'jumps' found at (20, 25)
'over' found at (26, 30)
'the' found at (31, 34)
'lazy' found at (35, 39)
'dog' found at (40, 43)
Number of word 'dog' found = 1

How do I sort strings data using CollationKey class?

When the strings must be compared multiple times, for example when sorting a list of strings. It’s more efficient to use CollationKey class. Using CollationKey to compare strings is generally faster than using Collator.compare().

You can not create CollationKey directly. Rather, generate them by calling Collator.getCollationKey() method. You can only compare CollationKey generated from the same Collator object.

package org.kodejava.text;

import java.text.CollationKey;
import java.text.Collator;
import java.util.Arrays;

public class CollationKeyExample {
    public static void main(String[] args) {
        String[] countries = {
                "German",
                "United Kingdom",
                "United States",
                "French",
                "Japan",
                "Myanmar",
                "India"
        };

        System.out.println("original:");
        System.out.println(Arrays.toString(countries));

        // Gets Collator object of default locale
        Collator collator = Collator.getInstance();

        // Creates and initializes CollationKey array
        CollationKey[] keys = new CollationKey[countries.length];

        for (int i = 0; i < countries.length; i++) {
            // Generate CollationKey by calling
            // Collator.getCollationKey() method then assign into
            // keys which is an array of CollationKey.
            // The CollationKey for the given String based on the 
            // Collator's collation rules.
            keys[i] = collator.getCollationKey(countries[i]);
        }

        // Sort the keys array
        Arrays.sort(keys);

        // Print out the sorted array
        System.out.println("sorted result: ");
        StringBuilder sb = new StringBuilder();
        for (CollationKey key : keys) {
            sb.append(key.getSourceString()).append(",");
        }
        System.out.println(sb);
    }
}

Below is the result of the program:

original:
[German, United Kingdom, United States, French, Japan, Myanmar, India]
sorted result: 
French,German,India,Japan,Myanmar,United Kingdom,United States,

How do I sort an array of string data using RuleBasedCollator class?

We can use the java.text.Collator class to sort strings in language-specific order. Using the java.text.Collator class makes the string not just sorted by the ASCII code of their characters, but it will follow the language natural order of the characters.

If the predefined collation rules do not meet your needs, you can design your own rules and assign them to a RuleBasedCollator object. Customized collation rules are contained in a String object that is passed to the RuleBasedCollator constructor.

package org.kodejava.text;

import java.text.ParseException;
import java.text.RuleBasedCollator;
import java.util.Arrays;

public class RuleBasedCollatorDemo {
    public static void main(String[] args) {
        String rule1 = ("< a < b < c");
        String rule2 = ("< c < b < a");
        String rule3 = ("< c < a < b");

        String[] words = {
                "apple",
                "banana",
                "carrot",
                "apricot",
                "blueberry",
                "cabbage"
        };

        try {
            RuleBasedCollator rb1 = new RuleBasedCollator(rule1);
            RuleBasedCollator rb2 = new RuleBasedCollator(rule2);
            RuleBasedCollator rb3 = new RuleBasedCollator(rule3);

            System.out.println("original: ");
            System.out.println(Arrays.toString(words));

            // Sort based on rule1
            Arrays.sort(words, rb1);
            System.out.println("rule: " + rb1.getRules());
            System.out.println(Arrays.toString(words));

            // Sort based on rule2
            Arrays.sort(words, rb2);
            System.out.println("rule: " + rb2.getRules());
            System.out.println(Arrays.toString(words));

            // Sort based on rule3
            Arrays.sort(words, rb3);
            System.out.println("rule: " + rb3.getRules());
            System.out.println(Arrays.toString(words));
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

Below is the result of sorting strings using a different RuleBasedCollator

original: 
[apple, banana, carrot, apricot, blueberry, cabbage]
rule: < a < b < c
[apple, apricot, banana, blueberry, cabbage, carrot]
rule: < c < b < a
[cabbage, carrot, banana, blueberry, apple, apricot]
rule: < c < a < b
[cabbage, carrot, apple, apricot, banana, blueberry]