DateTimeFormatter not work with LLLL pattern in en locale
Asked Answered
C

2

7

With ru locale return full month name (Февраль), but with en only number(2).

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("LLLL", new Locale("ru"));
LocalDate.now().format(formatter);

MMMM work with en, but not work with ru (need nominative case).

How get full month name for all locales?

Cobb answered 15/2, 2017 at 9:35 Comment(1)
also check this post: #30519454Drudgery
M
3

Unfortunately the related bug issue JDK-8114833 has not yet been solved for Java-8. And it is not yet clear for me if Java-9 offers a solution (and there the feature-freeze-date is already over). So you can either apply following workaround based on your knowledge which languages need a special standalone-form (nominative) for months and which not:

private static final Set<String> LANGUAGES_WITH_STANDALONE_CASE;

static {
    Set<String> set = new HashSet<>();
    set.add("ru");

    // add more languages which require LLLL-pattern (for example other slavish languages)
    LANGUAGES_WITH_STANDALONE_CASE = Collections.unmodifiableSet(set);
}

public static void main(String[] args) throws Exception {

    Locale locale = new Locale("en");

    DateTimeFormatter formatter =
      DateTimeFormatter.ofPattern(
        LANGUAGES_WITH_STANDALONE_CASE.contains(locale.getLanguage()) 
          ? "LLLL" : "MMMM",
        locale
      );
    System.out.println(LocalDate.now().format(formatter));

    // ru => Февраль
    // en => February
}

I cannot say that I like this solution because it requires extra knowledge which languages need which pattern. But it is actually the only possibility to solve your problem within the scope of JSR-310 (aka java.time-API).

By testing I see now that even the old class SimpleDateFormat (version in Java-8) works:

    Locale locale = new Locale("en");

    SimpleDateFormat sdf = new SimpleDateFormat("LLLL", locale);
    System.out.println(sdf.format(new Date()));

But that workaround has the strong disadvantage not to work with a plain calendar date but with java.util.Date only.

Or you might be willing to add an extra dependency to a library which has better support for the pattern letter "L" AND has better API-style AND better performance characteristics. For example you could use my library Time4J. Here a demonstration of latter case which also shows how the independent format engine of Time4J can be used for the JSR-310-types (also in parsing):

    Locale locale = new Locale("ru");

    ChronoFormatter<LocalDate> formatter =
        ChronoFormatter.ofPattern(
            "LLLL",
            PatternType.CLDR,
            locale,
            PlainDate.axis(TemporalType.LOCAL_DATE)
        );
    System.out.println(formatter.format(LocalDate.now()));

    // ru => Февраль
    // en => February

For best performance, I recommend to lazily store the formatter in a ConcurrentHashMap per locale.

Manaker answered 15/2, 2017 at 11:10 Comment(0)
G
-1

For nominative case you have to set the pattern to MM or LL instead of MMMM / LLLL

System.out.println(LocalDate.now().format(DateTimeFormatter.ofPattern("MM", new Locale("ru"))));
System.out.println(LocalDate.now().format(DateTimeFormatter.ofPattern("MM", new Locale("en"))));

that will print 02 for both locales

Gurango answered 15/2, 2017 at 9:46 Comment(1)
I think the OP wants full month names, not numbers.Manaker

© 2022 - 2024 — McMap. All rights reserved.