Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Modify DateFormatSymbols month values

Tags:

java

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.

like image 564
dboyd68 Avatar asked Oct 12 '11 16:10

dboyd68


2 Answers

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:

  • Eclipse ResourceBundle Editor (or on github)
  • Zaval Java Resource Editor

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.

like image 61
Addison Avatar answered Sep 28 '22 21:09

Addison


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:

  • You may provide your own CalendarNameProvider implementation.
  • You may use a 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

  • ICU Locale “norsk bokmål (Norge)” (nb_NO)
  • Oracle tutorial: Date Time
  • CalendarNameProvider documentation
  • DateTimeFormatterBuilder.appendText(TemporalField, Map) documentation
like image 38
Ole V.V. Avatar answered Sep 28 '22 22:09

Ole V.V.