Study guide

11.5 Formatting and Parsing Messages, Numbers, Percentages, and Localized Dates

Oracle Java SE 17 Developer Certified Professional 1Z0-829

Track your progress as you read

Finished sections get a check mark.

1 Introduction: The 1Z0-829 Exam

About the Java SE 17 Developer (1Z0-829) Exam

2 Chapter 1: Java Fundamentals & Language Basics

1.1 Primitive Types, Literals, Wrapper Classes, and Type Promotion/Casting 1.2 Local Variable Type Inference (`var`) Rules and Scoping 1.3 Operators, Precedence, Evaluation Order, and Short-Circuit Evaluation 1.4 Text Blocks, String Immutability, and StringBuilder APIs

3 Chapter 2: Program Flow & Decision Constructs

2.1 Conditional Branching with if/else and the Ternary Operator 2.2 Switch Statements and Switch Expressions 2.3 Iteration Constructs, Loop Control, and Branching Labels

4 Chapter 3: Object-Oriented Design & Class Mechanics

3.1 Class Declarations, Field/Method Signatures, and Access Modifiers 3.2 Constructors, Overloading, Initialization Order, and Garbage Collection 3.3 Inheritance, Method Overriding, Polymorphism, and `super`/`this` 3.4 Abstract Classes, Static Members, and Object Methods (`equals`, `hashCode`, `toString`)

5 Chapter 4: Advanced OOP: Interfaces, Records & Sealed Types

4.1 Interface Architecture: Default, Static, and Private Methods 4.2 Enumerations: Constants, Constructors, Methods, and Custom Bodies 4.3 Records: Canonical/Compact Constructors, Components, and Immutability 4.4 Sealed Classes and Interfaces: `permits`, Hierarchy Constraints, and Modifiers

6 Chapter 5: Pattern Matching & Nested Types

5.1 Pattern Matching for `instanceof` and Flow Scoping Mechanics 5.2 Nested Types: Member Inner, Static Nested, Local, and Anonymous Classes 5.3 Defensive Programming, Immutability Patterns, and Validation

7 Chapter 6: Generics, Collections & Arrays

6.1 Generic Classes, Interfaces, Methods, and Type Erasure 6.2 Bounded Type Parameters and Wildcards (PECS Rule) 6.3 Collections Framework: List, Set, Queue, and Deque APIs 6.4 The Map Interface, Sorting, Comparable, and Comparator 6.5 Arrays: Declaration, Initialization, Multidimensional Arrays, and the Arrays Utility Class

8 Chapter 7: Functional Programming & Lambda Expressions

7.1 Functional Interfaces and Lambda Syntax Rules 7.2 Standard Functional Interfaces in `java.util.function` 7.3 Method References: Static, Bound, Unbound, and Constructor References

9 Chapter 8: The Stream API

8.1 Stream Lifecycle: Creation, Pipeline Architecture, and Lazy Evaluation 8.2 Intermediate Stream Operations: Filtering, Mapping, Sorting, and Slicing 8.3 Terminal Stream Operations: Reduction, Matching, Finding, and Collecting 8.4 Primitive Streams (`IntStream`, `LongStream`, `DoubleStream`) and Numeric Statistics

10 Chapter 9: Advanced Streams & Collectors

9.1 The Optional Class: Safe Null Handling, Transformation, and Chaining 9.2 The Collectors API: Downstream Reductions, Grouping, and Partitioning 9.3 Parallel Streams: Fork/Join Pool, Spliterators, and Concurrency Pitfalls

11 Chapter 10: Exception Handling

10.1 The Java Exception Hierarchy: Checked vs. Unchecked Exceptions and Errors 10.2 Exception Constructs: `try-catch-finally`, Multi-Catch, and Rethrowing 10.3 Try-With-Resources, `AutoCloseable`, Suppressed Exceptions, and Custom Exceptions

12 Chapter 11: Date/Time API & Localization

11.1 Date and Time Core Types: `LocalDate`, `LocalTime`, `LocalDateTime` 11.2 Timestamps, Intervals, and Durations: `Instant`, `Period`, and `Duration` 11.3 Time Zones, Daylight Saving Time (DST) Offsets, and `ZonedDateTime` 11.4 Internationalization and Localization: `Locale`, `ResourceBundle`, and Formatters 11.5 Formatting and Parsing Messages, Numbers, Percentages, and Localized Dates

13 Chapter 12: Java Platform Module System (JPMS)

12.1 Module Architecture, `module-info.java`, and Module Paths 12.2 Module Directives: `requires`, `requires transitive`, `exports`, and Qualified Exports 12.3 Reflection, Deep Encapsulation, `opens`, and Open Modules 12.4 Services in JPMS (`uses`, `provides...with`), Migration Paths, and Tooling (`jlink`, `jdeps`) 12.5 Compiling and Packaging Code: Non-Modular JARs, Modular JARs, and Migration Strategies

14 Chapter 13: Concurrency & Multithreading

13.1 Thread Fundamentals, `Runnable`, `Callable`, and Thread Lifecycle 13.2 Memory Visibility, `volatile`, Intrinsic Locks, and Synchronization 13.3 The Concurrency Framework: `ExecutorService`, Thread Pools, and `Future` 13.4 Concurrent Collections, Atomic Variables, Explicit Locks, and `CompletableFuture`

15 Chapter 14: Java I/O and NIO.2

14.1 Classical I/O: Byte and Character Streams, Readers, Writers, and Buffering 14.2 Object Serialization, `Serializable`, `transient`, and `serialVersionUID` 14.3 NIO.2 Architecture: `Path`, `Paths`, and Basic `Files` Operations 14.4 Advanced NIO.2: Directory Walking, Streams (`Files.lines`, `walk`), and `WatchService`

16 Chapter 15: Accessing Databases with JDBC

15.1 JDBC Architecture, Drivers, `DriverManager`, and `DataSource` Connections 15.2 SQL Execution: `Statement`, `PreparedStatement`, and `CallableStatement` 15.3 `ResultSet` Navigation, Data Types, and Transaction Management (Commit, Rollback, Savepoints)

17 Chapter 16: Annotations & the Java Logging API

16.1 Standard Annotations: @Override, @FunctionalInterface, @Deprecated, @SuppressWarnings, and @SafeVarargs 16.2 Java Logging API Basics: Logger, Levels, Handlers, and Configuration

11.5 Formatting and Parsing Messages, Numbers, Percentages, and Localized Dates

Key Takeaways Explain This Topic AI

MessageFormat replaces numbered placeholders such as {0} and {1,number,currency} by argument index, so a pattern can reorder arguments for each language.

In a MessageFormat pattern a single quote starts literal text, so It's {0} prints Its {0}; write two single quotes for an apostrophe.

NumberFormat.getPercentInstance(Locale.US) formats 0.256 as 26% because percent formats multiply by 100 and show no fraction digits by default.

NumberFormat.parse declares the checked ParseException, and a US currency parser rejects a number without the dollar sign.

DateTimeFormatter is immutable and thread-safe, while NumberFormat, DecimalFormat, and MessageFormat instances are not thread-safe.

Last updated: October 2026

11.5 Formatting and Parsing Messages, Numbers, Percentages, and Localized Dates

The localization objective asks you to "parse and format messages, dates, times, and numbers including currency and percentage values." Section 11.4 introduced Locale , resource bundles, and the basic NumberFormat and DateTimeFormatter factories. This section completes the objective with MessageFormat , percentage and compact number formats, DecimalFormat patterns, parsing rules, and locale-sensitive date output.

Formatting Messages with java.text.MessageFormat

Resource bundle values often contain numbered placeholders that are filled in at runtime. MessageFormat replaces {0} , {1} , and so on with arguments in index order, regardless of where they appear in the pattern: String msg = MessageFormat.format("{0} has {1} items costing {2,number,currency}", "Ana", 3, 9.5);

  • System.out.println(msg); // Ana has 3 items costing $9.50 (en_US default)
  • System.out.println(MessageFormat.format("{1} before {0}", "A", "B")); // B before A
  • System.out.println(MessageFormat.format("{0}", 1234567)); // 1,234,567
  • System.out.println(MessageFormat.format("{0,number,percent}", 0.5)); // 50%

A placeholder can name a format type and style : {n,number} , {n,number,integer} , {n,number,currency} , {n,number,percent} , {n,date,short} , or {n,time,medium} . Numbers are localized even without a type, which is why 1234567 printed with grouping separators.

For a specific locale, create an instance instead of calling the static method: MessageFormat mf = new MessageFormat("{0,number,currency}", Locale.GERMANY);

System.out.println(mf.format(new Object[] {9.5})); // 9,50 €

Warning

The apostrophe trap. In a MessageFormat pattern, a single quote starts a quoted (literal) section. MessageFormat.format("It's {0}", "x") prints Its {0} : the quote disappears and the placeholder is never replaced. Write two single quotes for a literal apostrophe: "It''s {0}" prints It's x . Translators who store It's {0} in a .properties file hit exactly this bug.

Combining a bundle with MessageFormat is the standard localization pattern: ResourceBundle rb = ResourceBundle.getBundle("Messages", new Locale("en", "US"));

// Messages_en_US.properties contains: greeting=Hello, {0}! You have {1} new messages.

String text = MessageFormat.format(rb.getString("greeting"), "Ravi", 4);

// Hello, Ravi! You have 4 new messages.

String.format (with %s , %d , %.2f ) is a different API that uses the default FORMAT locale. After Locale.setDefault(Locale.Category.FORMAT, Locale.GERMANY) , String.format("%.2f", 1234.5) returns 1234,50 , while String.format(Locale.US, "%.2f", 1234.5) returns 1234.50 .

Number, Currency, Percentage, and Compact Formats

java.text.NumberFormat provides locale-aware factories. All of them are not thread-safe , unlike DateTimeFormatter .

  • Factory Example ( Locale.US unless noted) Output
  • NumberFormat.getInstance() / getNumberInstance() format(3.14159) 3.142 (at most 3 fraction digits by default)
  • NumberFormat.getIntegerInstance() format(2.5) / format(3.5) 2 / 4 (rounding mode HALF_EVEN )
  • NumberFormat.getCurrencyInstance() format(49.99) $49.99 ; in Locale.GERMANY , 49,99 €
  • NumberFormat.getPercentInstance() format(0.256) / format(1.5) 26% / 150% ; in Locale.FRANCE , 26 %
  • NumberFormat.getCompactNumberInstance(locale, Style.SHORT) (Java 12) format(1_250_000) / format(1_550) 1M / 2K
  • NumberFormat.getCompactNumberInstance(locale, Style.LONG) format(2_000) 2 thousand

Remember that a percent format multiplies by 100: the value 0.256 is 25.6%, which rounds to 26% because the percent instance shows no fraction digits by default.

Custom patterns with DecimalFormat

DecimalFormat (a NumberFormat subclass) uses pattern symbols: 0 always prints a digit (padding with zeros), # prints a digit only when needed, , marks grouping, and . marks the decimal separator. System.out.println(new DecimalFormat("#,##0.00").format(1234.5)); // 1,234.50

  • System.out.println(new DecimalFormat("000.##").format(3.14159)); // 003.14
  • System.out.println(new DecimalFormat("0.0").format(2.25)); // 2.2 (HALF_EVEN tie goes to the even digit)
  • Parsing Numbers and Currency

NumberFormat.parse(String) returns a Number ( Long when the value is integral, otherwise Double ) and declares the checked java.text.ParseException : NumberFormat cf = NumberFormat.getCurrencyInstance(Locale.US);

  • System.out.println(cf.parse("$1,234.50")); // 1234.5
  • System.out.println(NumberFormat.getPercentInstance(Locale.US).parse("26%")); // 0.26
  • cf.parse("1234.50"); // throws ParseException: Unparseable number: "1234.50" (no $ prefix)

A currency parser expects the locale's currency symbol, and a percent parser divides by 100. As section 11.4 showed, parsing stops at the first character that cannot belong to a number, so "45.67xyz" parses as 45.67 , but text that cannot start a number throws ParseException .

Locale-Sensitive Dates and Times

DateTimeFormatter styles produce different text for each locale. Use withLocale (or the locale argument of ofPattern ) to choose it: LocalDate d = LocalDate.of(2026, 4, 15);

  • DateTimeFormatter medium = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);
  • System.out.println(medium.withLocale(Locale.US).format(d)); // Apr 15, 2026
  • System.out.println(medium.withLocale(Locale.FRANCE).format(d)); // 15 avr. 2026
  • System.out.println(medium.withLocale(Locale.GERMANY).format(d)); // 15.04.2026
  • System.out.println(DateTimeFormatter.ofPattern("EEEE d MMMM", Locale.FRANCE).format(d)); // mercredi 15 avril

Month and day names ( MMMM , EEEE ) come from the formatter's locale, while numeric patterns such as dd/MM/yyyy look the same everywhere. Parsing uses the same formatter: LocalDate.parse("15/04/2026", DateTimeFormatter.ofPattern("dd/MM/yyyy")) succeeds, and a mismatch throws the unchecked DateTimeParseException .

  • API Thread-safe? Parse failure
  • DateTimeFormatter Yes (immutable) DateTimeParseException (unchecked)
  • NumberFormat , DecimalFormat , MessageFormat No ParseException (checked)