I am trying to add specific month names for a particular locale. The issue I have is with locale for norwegian bokmal (nb) the names of the months returned by SimpleDateFormat are in English not norweigan. However it seems that locale (no) works fine
e.g. This code results in January, February, etc.
String pattern = "MMMM";
DateFormat monthFormat = new SimpleDateFormat(pattern, new Locale("nb"));
Calendar cal = Calendar.getInstance();
for (int i = 0; i < 12; i++) {
cal.set(Calendar.MONTH, i);
System.out.println(monthFormat.format(cal.getTime()));
}
vs this code which results in Januar, Februar etc
String pattern = "MMMM";
DateFormat monthFormat = new SimpleDateFormat(pattern, new Locale("no"));
Calendar cal = Calendar.getInstance();
for (int i = 0; i < 12; i++) {
cal.set(Calendar.MONTH, i);
System.out.println(monthFormat.format(cal.getTime()));
}
I know I can configure SimpleDateFormat with a specific DateFormatSymbols however this doesn't help keep my code generic for any future locals. I was wondering if anyone knows how to modify the default month values for a supported java locale? I figured there would be a resource file I could add but couldn't figure out how.
Looking at the constructor being used in the source code for SimpleDateFormat
:
public SimpleDateFormat(String pattern, Locale locale) {
super();
calendar = new GregorianCalendar(locale);
...
formatData = new DateFormatSymbols(locale);
...
numberFormat = NumberFormat.getInstance(locale);
...
}
The first and last instances of locale being used (GregorianCalendar
) and (NumberFormat
) don't look promising, but the middle one (DateFormatSymbols
) does. Looking at its source code, we see a ResourceBundle
in the first line of the Constructor:
public DateFormatSymbols (Locale locale) throws MissingResourceException {
ResourceBundle res = ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
locale, ClassLoader.getSystemClassLoader()); // This line!
ampms = getStringArray(res, "ampms");
eras = getStringArray(res, "eras");
localPatternChars = res.getString("localPatternChars");
months = getStringArray(res, "months");
shortMonths = getStringArray(res, "shortMonths");
shortWeekdays = getStringArray(res, "shortWeekdays");
weekdays = getStringArray(res, "weekdays");
runtimeZoneStrings = getZoneStrings(res, locale);
dateFormats = formatsForKey(res, "DateFormat");
timeFormats = formatsForKey(res, "TimeFormat");
}
This is the Resource Bundle you'll have to edit. There are plenty of tools out there to do it:
Once you've edited and saved your ResourceBundle, you'll have to extend both of these classes - Your extended DateFormatSymbols will need to use your new ResourceBundle, and your extended SimpleDateFormat will need to use that new extended class.
If you're in need of more resources, consider looking at this oracle article.
Newer Java versions do support the nb
(norsk bokmål) locale:
Locale bokmaal = Locale.forLanguageTag("nb");
for (Month m : Month.values()) {
System.out.println(m.getDisplayName(TextStyle.FULL, bokmaal));
}
Output on my Java 9.0.4:
januar
februar
mars
april
mai
juni
juli
august
september
oktober
november
desember
On Java 1.8.0_101 I get identical output.
This is 2018, so of course I am using java.time, the modern Java date and time API (and no longer the poorly designed DateFormat
, SimpleDateFormat
and Calendar
).
For anyone ending here wanting to provide names for a different locale (or not being satisfied with the output you get from the nb
locale), there are a couple of options:
CalendarNameProvider
implementation.DateTimeFormatterBuilder
and the overloaded version of its appendText
method that accepts a map of names to use for formatting and parsing.There’s more in this questions: SimpleDateFormat with German Locale - Java 8 vs Java 10.
Links
CalendarNameProvider
documentationDateTimeFormatterBuilder.appendText(TemporalField, Map)
documentationIf you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With