Formatting Dates, Times, Numbers, and Currency
Overview
Java provides dedicated classes for locale-aware formatting and parsing of dates, times, numbers, and currencies:
| Class | Package | Purpose |
|---|---|---|
DateTimeFormatter |
java.time.format |
Format and parse LocalDate, LocalTime, LocalDateTime, ZonedDateTime |
NumberFormat |
java.text |
Locale-aware number, currency, and percentage formatting |
DecimalFormat |
java.text |
Custom numeric patterns (e.g., #,##0.00) |
Currency |
java.util |
Currency metadata (symbol, code, fraction digits) |
DateTimeFormatter
DateTimeFormatter is immutable and thread-safe. It can both format (date → string) and parse (string → date).
Predefined Formatters
javaDateTimeFormatter.ISO_LOCAL_DATE // "2025-06-15"
DateTimeFormatter.ISO_LOCAL_DATE_TIME // "2025-06-15T10:30:00"
DateTimeFormatter.ISO_ZONED_DATE_TIME // "2025-06-15T10:30:00+01:00[Europe/London]"Pattern-Based Formatter
javaDateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd/MM/yyyy");
LocalDate date = LocalDate.of(2025, 6, 15);
String formatted = date.format(fmt); // "15/06/2025"
LocalDate parsed = LocalDate.parse("15/06/2025", fmt); // LocalDateCommon pattern letters:
| Symbol | Meaning | Example |
|---|---|---|
yyyy |
Year (4 digits) | 2025 |
yy |
Year (2 digits) | 25 |
MM |
Month (2 digits) | 06 |
MMM |
Month abbreviation | Jun |
MMMM |
Month full name | June |
dd |
Day of month | 15 |
HH |
Hour (0–23) | 10 |
hh |
Hour (1–12) | 10 |
mm |
Minutes | 30 |
ss |
Seconds | 00 |
a |
AM/PM marker | PM |
z |
Time-zone name | EDT |
Z |
Zone offset | -0400 |
javaDateTimeFormatter dtFmt = DateTimeFormatter.ofPattern("MMMM dd, yyyy 'at' HH:mm");
LocalDateTime ldt = LocalDateTime.of(2025, 6, 15, 10, 30);
ldt.format(dtFmt); // "June 15, 2025 at 10:30"Locale-Aware Pattern Formatter
Pass a locale to ofPattern() to control locale-specific elements (month names, AM/PM text):
javaDateTimeFormatter fmtFR = DateTimeFormatter.ofPattern("MMMM dd, yyyy", Locale.FRANCE);
LocalDate.of(2025, 6, 15).format(fmtFR); // "juin 15, 2025"Localized Formatters — ofLocalizedDate() and ofLocalizedDateTime()
FormatStyle controls the verbosity of a localized format:
| FormatStyle | Date example (en_US) |
|---|---|
SHORT |
6/15/25 |
MEDIUM |
Jun 15, 2025 |
LONG |
June 15, 2025 |
FULL |
Sunday, June 15, 2025 |
javaDateTimeFormatter shortFmt = DateTimeFormatter
.ofLocalizedDate(FormatStyle.SHORT)
.withLocale(Locale.US);
DateTimeFormatter fullFmt = DateTimeFormatter
.ofLocalizedDate(FormatStyle.FULL)
.withLocale(Locale.FRANCE);
LocalDate d = LocalDate.of(2025, 6, 15);
d.format(shortFmt); // "6/15/25"
d.format(fullFmt); // "dimanche 15 juin 2025"For date-time formatting, use ofLocalizedDateTime(dateStyle, timeStyle):
javaDateTimeFormatter dtFmt = DateTimeFormatter
.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.SHORT)
.withLocale(Locale.US);
LocalDateTime.of(2025, 6, 15, 10, 30).format(dtFmt);
// "Jun 15, 2025, 10:30 AM"Parsing with DateTimeFormatter
javaDateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
LocalDateTime ldt = LocalDateTime.parse("2025-06-15 10:30", fmt);
LocalDate ld = LocalDate.parse("2025-06-15"); // ISO format, no formatter neededExam tip:
LocalDate.parse()andLocalDateTime.parse()without a formatter useISO_LOCAL_DATEandISO_LOCAL_DATE_TIMErespectively. A formatter must be provided if the string uses a different pattern.
NumberFormat
NumberFormat is the base class for locale-aware formatting of numbers, currencies, and percentages. Obtain instances via factory methods — do not construct directly.
Factory Methods
javaNumberFormat nf = NumberFormat.getInstance(Locale.US); // general number
NumberFormat curr = NumberFormat.getCurrencyInstance(Locale.US); // currency
NumberFormat pct = NumberFormat.getPercentInstance(Locale.US); // percentage
NumberFormat intF = NumberFormat.getIntegerInstance(Locale.US); // integer (truncates)Formatting Numbers
javaNumberFormat nf = NumberFormat.getInstance(Locale.US);
nf.format(1234567.89); // "1,234,567.89"
NumberFormat nfDE = NumberFormat.getInstance(Locale.GERMANY);
nfDE.format(1234567.89); // "1.234.567,89" (German uses . for grouping, , for decimal)Currency Formatting
javaNumberFormat curr = NumberFormat.getCurrencyInstance(Locale.US);
curr.format(1234.5); // "$1,234.50"
NumberFormat currFR = NumberFormat.getCurrencyInstance(Locale.FRANCE);
currFR.format(1234.5); // "1 234,50 €"Percentage Formatting
javaNumberFormat pct = NumberFormat.getPercentInstance(Locale.US);
pct.format(0.75); // "75%"
pct.format(1.5); // "150%"Integer Formatting
javaNumberFormat intF = NumberFormat.getIntegerInstance(Locale.US);
intF.format(1234.9); // "1,235" (rounds to nearest integer)Controlling Fraction Digits
javaNumberFormat nf = NumberFormat.getInstance(Locale.US);
nf.setMinimumFractionDigits(2);
nf.setMaximumFractionDigits(4);
nf.format(3.1); // "3.10"
nf.format(3.14159); // "3.1416"Parsing with NumberFormat
javaNumberFormat nf = NumberFormat.getInstance(Locale.US);
Number n = nf.parse("1,234.56"); // 1234.56 as a Double
double d = n.doubleValue();
NumberFormat curr = NumberFormat.getCurrencyInstance(Locale.US);
Number amount = curr.parse("$1,234.50"); // 1234.5Exam tip:
NumberFormat.parse()throws the checkedParseException. The return type isNumber, notdouble— calldoubleValue()orintValue()on the result.
DecimalFormat
DecimalFormat applies a custom pattern to numeric values. It is a subclass of NumberFormat.
Pattern Characters
| Symbol | Meaning |
|---|---|
0 |
Required digit (shows 0 if absent) |
# |
Optional digit (suppressed if absent) |
. |
Decimal separator position |
, |
Grouping separator |
% |
Multiply by 100 and show as percentage |
E |
Scientific notation |
' |
Escape literal text |
javaDecimalFormat df = new DecimalFormat("#,##0.00");
df.format(1234.5); // "1,234.50"
df.format(0.5); // "0.50"
df.format(1234567); // "1,234,567.00"
DecimalFormat pct = new DecimalFormat("#0.0%");
pct.format(0.756); // "75.6%"
DecimalFormat sci = new DecimalFormat("0.###E0");
sci.format(123456); // "1.235E5"Locale-Aware DecimalFormat
By default, DecimalFormat uses the JVM default locale's decimal and grouping symbols. To use a specific locale, obtain the symbols explicitly:
javaDecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(Locale.GERMANY);
DecimalFormat df = new DecimalFormat("#,##0.00", symbols);
df.format(1234.5); // "1.234,50"Currency
Currency holds ISO 4217 currency metadata. It does not perform formatting — use NumberFormat.getCurrencyInstance() for that.
javaCurrency eur = Currency.getInstance("EUR");
Currency usd = Currency.getInstance("USD");
Currency jpy = Currency.getInstance("JPY");
eur.getCurrencyCode(); // "EUR"
eur.getSymbol(); // "€" (in default locale)
eur.getSymbol(Locale.US); // "EUR" (symbol in a given locale)
eur.getSymbol(Locale.FRANCE); // "€"
eur.getDisplayName(); // "Euro"
eur.getDefaultFractionDigits(); // 2
jpy.getDefaultFractionDigits(); // 0 (Japanese Yen has no subunit)Currency from Locale
javaCurrency localCurrency = Currency.getInstance(Locale.US); // USDExam tip:
Currency.getInstance(String)takes an ISO 4217 currency code (uppercase, 3 letters).Currency.getInstance(Locale)takes a locale and derives the currency from the country.getSymbol()returns the locale-sensitive symbol, not always€or$— it depends on the display locale.
Key Points for the Exam
DateTimeFormatter.ofPattern()defines a custom format; letters are case-sensitive (MM= month,mm= minutes).ofLocalizedDate(FormatStyle)+withLocale(locale)produces a locale-aware formatter without a hardcoded pattern.LocalDate.parse(string, formatter)anddate.format(formatter)are symmetric operations.NumberFormatfactory methods:getInstance,getCurrencyInstance,getPercentInstance,getIntegerInstance— all accept an optionalLocale.NumberFormat.parse()returnsNumber, throws checkedParseException.DecimalFormatpattern:0is a required digit,#is optional;#,##0.00is a common currency-like pattern.Currency.getInstance("EUR")retrieves metadata; usegetCurrencyInstance(locale)onNumberFormatfor actual formatting.