Internationalization with Dates in Java
The same date is written differently around the world. 4 March 2026 is 3/4/26 in the United States, 04/03/2026 in Britain and 04.03.26 in Germany. A reader who sees 03/04/2026 can't know whether it means March or April without knowing where it was written. Java solves this with DateTimeFormatter used together with a Locale: you choose how detailed the date should be, and Java supplies the order, the separators and the month names for the reader's region. In this lesson, you will learn the four format styles, how names are translated, how patterns and locales combine, and how to parse a localized date.
"DateTimeFormatter in Java" covers formatters in general; this lesson is about making them follow a locale.
Methods
| Method | Description |
|---|---|
DateTimeFormatter.ofLocalizedDate(style) | It is used to create a formatter for dates in a given style. |
formatter.withLocale(locale) | It returns a copy of the formatter that uses the given locale. |
DateTimeFormatter.ofPattern(pattern, locale) | It creates a fixed-layout formatter whose names follow the locale. |
Month.getDisplayName(textStyle, locale), DayOfWeek.getDisplayName(...) | They return a translated month or day name. |
WeekFields.of(locale).getFirstDayOfWeek() | It returns the day a week starts on in that region. |
The Four Styles
FormatStyle | Detail | US example |
|---|---|---|
FULL | Weekday, day, full month, year | Wednesday, March 4, 2026 |
LONG | Day, full month, year | March 4, 2026 |
MEDIUM | Shortened month or numbers | Mar 4, 2026 |
SHORT | Numbers only | 3/4/26 |
Example: One Date, Six Locales
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.Month;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.time.format.TextStyle;
import java.time.temporal.WeekFields;
import java.util.Locale;
public class Dates {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2026, 3, 4);
Locale[] locales = {Locale.US, Locale.UK, Locale.GERMANY,
Locale.FRANCE, Locale.of("hi", "IN"), Locale.JAPAN};
for (FormatStyle style : FormatStyle.values()) {
System.out.println(style + ":");
for (Locale locale : locales) {
DateTimeFormatter f = DateTimeFormatter
.ofLocalizedDate(style).withLocale(locale);
System.out.println(" " + locale.toLanguageTag()
+ " " + date.format(f));
}
}
System.out.println("Names:");
for (Locale locale : locales) {
System.out.println(" " + locale.toLanguageTag() + " "
+ Month.MARCH.getDisplayName(TextStyle.FULL, locale) + ", "
+ DayOfWeek.WEDNESDAY.getDisplayName(TextStyle.FULL, locale)
+ ", week starts on "
+ WeekFields.of(locale).getFirstDayOfWeek());
}
// A pattern fixes the layout but still translates the names.
DateTimeFormatter pattern =
DateTimeFormatter.ofPattern("EEEE, d MMMM uuuu");
System.out.println(date.format(pattern.withLocale(Locale.FRANCE)));
// Parsing needs the same locale that wrote the text.
DateTimeFormatter german = DateTimeFormatter
.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(Locale.GERMANY);
System.out.println(LocalDate.parse("04.03.2026", german));
}
}FULL:
en-US Wednesday, March 4, 2026
en-GB Wednesday, 4 March 2026
de-DE Mittwoch, 4. März 2026
fr-FR mercredi 4 mars 2026
hi-IN बुधवार, 4 मार्च 2026
ja-JP 2026年3月4日水曜日
LONG:
en-US March 4, 2026
en-GB 4 March 2026
de-DE 4. März 2026
fr-FR 4 mars 2026
hi-IN 4 मार्च 2026
ja-JP 2026年3月4日
MEDIUM:
en-US Mar 4, 2026
en-GB 4 Mar 2026
de-DE 04.03.2026
fr-FR 4 mars 2026
hi-IN 4 मार्च 2026
ja-JP 2026/03/04
SHORT:
en-US 3/4/26
en-GB 04/03/2026
de-DE 04.03.26
fr-FR 04/03/2026
hi-IN 4/3/26
ja-JP 2026/03/04
Names:
en-US March, Wednesday, week starts on SUNDAY
en-GB March, Wednesday, week starts on MONDAY
de-DE März, Mittwoch, week starts on MONDAY
fr-FR mars, mercredi, week starts on MONDAY
hi-IN मार्च, बुधवार, week starts on SUNDAY
ja-JP 3月, 水曜日, week starts on SUNDAY
mercredi, 4 mars 2026
2026-03-04Explanation:
- Each style is printed for six locales. The program never mentions an order or a separator:
ofLocalizedDate(style).withLocale(locale)does it all. SHORTshows the danger of fixed formats. The US prints3/4/26and India4/3/26for the same day.- Names come from
getDisplayName: March is "März" in German and "mars" in French, which doesn't capitalize month names. - The week starts on Sunday in the US, India and Japan, and on Monday in Britain, Germany and France. A calendar screen needs this.
- A pattern with a locale keeps your layout (
EEEE, d MMMM uuuu) but still translates the names: "mercredi, 4 mars 2026". - Parsing uses the same formatter and locale that produced the text, turning
04.03.2026back into aLocalDate.
Style or Pattern?
| Use | When |
|---|---|
ofLocalizedDate(style) | Text shown to people. The layout follows each region's custom. |
ofPattern(...) with a locale | You need a specific layout but want translated names. |
DateTimeFormatter.ISO_LOCAL_DATE (2026-03-04) | Data for programs: files, JSON, databases, URLs. It never depends on a locale. |
Common Mistakes
Forgetting withLocale. The formatter uses the JVM's default locale, which on a server is the server's, not the reader's.
Parsing user input with the wrong locale. 04/03/2026 is 4 March in Britain and April 3 in the US.
Using localized dates in file names or data. They change with the locale and don't sort correctly.
Comparing output across JDK versions character by character. The locale data (CLDR) is updated, and details such as punctuation can change.
Practice
- Easy: Print today's date in
FULLstyle forLocale.ITALY,Locale.KOREAandLocale.of("te", "IN"). - Harder: Print the seven day names of a week for a given locale, starting with that locale's first day of the week.
Key Takeaways
Was this tutorial helpful?