Back to Stream Practice: Employee Analysis
Q20Question 20 of 43

Format an employee's joining date as dd-MMM-yyyy using DateTimeFormatter

Key Concepts
  • DateTimeFormatter.ofPattern("dd-MMM-yyyy") creates a formatter for patterns like 15-Jan-2021
  • MMM produces a 3-letter month abbreviation; MM produces a 2-digit month number
  • The formatter is thread-safe and should be stored as a static final constant
  • Use withLocale(Locale.ENGLISH) to ensure month names are in English regardless of system locale
  • format() converts LocalDate to String; parse() converts String to LocalDate
  • map(e -> e.getJoinDate().format(formatter)) transforms the stream for display

Definition

DateTimeFormatter.ofPattern("dd-MMM-yyyy") formats a LocalDate like 15-Jan-2021, and you apply it in a stream with map(e -> e.getJoinDate().format(formatter)).
  • DateTimeFormatter.ofPattern(pattern) creates a formatter from a pattern string.
  • dd = 2-digit day, MMM = 3-letter month abbreviation, yyyy = 4-digit year.
  • Thread-safe: DateTimeFormatter is immutable and safe to share as a static final constant.
  • Locale: use withLocale(Locale.ENGLISH) to ensure English month names.
  • format() converts LocalDate to String; parse() does the reverse.

Priya at the National Bank of India generates a staff report where each joining date must appear as '15-Jan-2021' instead of '2021-01-15'. The formatter is like a stamp template: every date pressed through it comes out in the same human-readable format.

Understanding the Concepts

What does this question ask?

The interviewer wants you to format dates using the java.time API. This tests DateTimeFormatter pattern syntax, locale awareness, and stream integration.

How do you format joining dates in a stream?

JAVA
package com.bank.hr;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.Locale;

public class FormatJoinDate {
    private static final DateTimeFormatter FORMATTER =
        DateTimeFormatter.ofPattern("dd-MMM-yyyy", Locale.ENGLISH);

    public static void main(String[] args) {
        List<Employee> employees = Employee.getSampleEmployees();

        employees.stream()
            .sorted(Comparator.comparing(Employee::getJoinDate))
            .forEach(e -> System.out.println(
                e.getName() + ": " + e.getJoinDate().format(FORMATTER)));
    }
}
TEXT
Suresh: 01-Apr-2005
Rajesh: 01-Mar-2015
Amit: 10-Sep-2018
Kavita: 01-Jul-2019
Priya: 01-Jun-2021
Neha: 15-Mar-2022
Ananya: 10-Jan-2023
Meera: 20-Jul-2024

What do the pattern letters mean?

| Pattern | Meaning | Example |
|---|---|---|
| dd | Day of month (2 digits, zero-padded) | 01, 15, 31 |
| d | Day of month (1-2 digits) | 1, 15, 31 |
| MMM | Month abbreviation (3 letters) | Jan, Feb, Dec |
| MM | Month number (2 digits) | 01, 06, 12 |
| MMMM | Full month name | January, June |
| yyyy | Year (4 digits) | 2021, 2024 |
| yy | Year (2 digits) | 21, 24 |
| EEEE | Full day name | Monday, Friday |
| EEE | Day abbreviation | Mon, Fri |

JAVA
// Different patterns
LocalDate date = LocalDate.of(2021, 6, 15);

System.out.println(date.format(DateTimeFormatter.ofPattern("dd/MM/yyyy")));
// 15/06/2021

System.out.println(date.format(DateTimeFormatter.ofPattern("MMMM dd, yyyy", Locale.ENGLISH)));
// June 15, 2021

System.out.println(date.format(DateTimeFormatter.ofPattern("EEE, dd MMM yyyy", Locale.ENGLISH)));
// Tue, 15 Jun 2021

Why is Locale important?

Without specifying a locale, MMM uses the system default locale, which could produce month names in Hindi, Japanese, or any other language.

JAVA
// WRONG: depends on system locale
DateTimeFormatter wrong = DateTimeFormatter.ofPattern("dd-MMM-yyyy");
// On a Hindi system: 15-जून-2021

// CORRECT: explicit English locale
DateTimeFormatter correct = DateTimeFormatter.ofPattern(
    "dd-MMM-yyyy", Locale.ENGLISH);
// Always: 15-Jun-2021

What are common mistakes?

Mistake 1: using mm instead of MM for months.

JAVA
// WRONG: mm is minutes, not months!
DateTimeFormatter wrong = DateTimeFormatter.ofPattern("dd-mm-yyyy");
// Throws DateTimeException: "Field MinuteOfHour cannot be printed"

// CORRECT: MM is months
DateTimeFormatter correct = DateTimeFormatter.ofPattern("dd-MM-yyyy");

Mistake 2: creating a new formatter inside the stream for every element.

JAVA
// WRONG: creates a new formatter for every employee
employees.stream()
    .map(e -> e.getJoinDate().format(
        DateTimeFormatter.ofPattern("dd-MMM-yyyy")))  // new formatter each time!
    .toList();

// CORRECT: reuse a static final formatter
private static final DateTimeFormatter FMT =
    DateTimeFormatter.ofPattern("dd-MMM-yyyy", Locale.ENGLISH);
employees.stream()
    .map(e -> e.getJoinDate().format(FMT))
    .toList();

How do you parse a formatted string back to LocalDate?

JAVA
String dateStr = "15-Jun-2021";
LocalDate parsed = LocalDate.parse(dateStr,
    DateTimeFormatter.ofPattern("dd-MMM-yyyy", Locale.ENGLISH));
System.out.println(parsed);  // 2021-06-15

How do you build a formatted report with streams?

JAVA
String report = employees.stream()
    .sorted(Comparator.comparing(Employee::getJoinDate))
    .map(e -> String.format("%-10s %-12s %s",
        e.getName(),
        e.getDepartment(),
        e.getJoinDate().format(FORMATTER)))
    .collect(Collectors.joining("\n"));

System.out.println(report);

What are common interview follow-up questions?

  • "How do you format with time?" Use DateTimeFormatter.ofPattern("dd-MMM-yyyy HH:mm:ss") with LocalDateTime.
  • "Is DateTimeFormatter thread-safe?" Yes, it is immutable and safe for concurrent use.
  • "How do you handle invalid date strings during parse?" Catch DateTimeParseException.

Visual Overview

DIAGRAM
  LocalDate: 2021-06-15
       │
       │  .format(DateTimeFormatter.ofPattern("dd-MMM-yyyy"))
       ▼
  Pattern parsing:
  ┌──────────────────────────────────┐
  │  dd   → 15  (day, zero-padded)  │
  │  -    → -   (literal)           │
  │  MMM  → Jun (month abbreviation)│
  │  -    → -   (literal)           │
  │  yyyy → 2021 (4-digit year)     │
  └──────────────────────────────────┘
       │
       ▼
  String: "15-Jun-2021"

Key Takeaway

Formatting dates uses DateTimeFormatter.ofPattern with pattern letters: dd for day, MMM for month abbreviation, yyyy for year. The expression date.format(DateTimeFormatter.ofPattern("dd-MMM-yyyy", Locale.ENGLISH)) produces strings like "15-Jun-2021".

Always specify Locale.ENGLISH explicitly. Without it, MMM uses the system locale, which could produce month names in Hindi, Japanese, or any other language. Store the formatter as a static final constant because it is immutable and thread-safe.

The most common mistake is using lowercase mm (minutes) instead of uppercase MM (months). The formatter is case-sensitive: mm throws DateTimeException when applied to a LocalDate because LocalDate has no minute field.

Remember one sentence: DateTimeFormatter.ofPattern with dd-MMM-yyyy and an explicit Locale formats dates consistently, and always store the formatter as a static final constant.

---

Share
Use ← → arrow keys to navigate