Proper Russian month string translation Java

On my JDK-6-installation I can reproduce your problem:

Date jud = new SimpleDateFormat("yyyy-MM-dd").parse("2014-02-28");
String month =
    DateFormat.getDateInstance(SimpleDateFormat.LONG, new Locale("ru")).format(jud);
System.out.println(month); // output: 28 Февраль 2014 г.

Java-8 offers you a solution.

It seems that the JDK has changed the internal default from "standalone-style" (nominative) to "format-style" (genitive).

String date =
  DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)
  .withLocale(new Locale("ru"))
  .format(LocalDate.of(2014, 2, 28));
System.out.println(date); // output: 28 февраля 2014 г.

If you need to apply standalone textstyle then you have to set up your own DateTimeFormatterBuilder which requires a little bit more effort, else TextStyle.FULL should be the default.

String m = Month.FEBRUARY.getDisplayName(TextStyle.FULL , new Locale("ru")); 
// февраля (first and last char are different)

String s = Month.FEBRUARY.getDisplayName(TextStyle.FULL_STANDALONE , new Locale("ru")); 
// Февраль (this style can be used in DateTimeFormatterBuilder for the month field, too)

Workaround for Java-pre-8 using old style:

Define your own text resources (troublesome)!

Locale russian = new Locale("ru");
String[] newMonths = {
  "января", "февраля", "марта", "апреля", "мая", "июня", 
  "июля", "августа", "сентября", "октября", "ноября", "декабря"};
DateFormatSymbols dfs = DateFormatSymbols.getInstance(russian);
dfs.setMonths(newMonths);
DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, russian);
SimpleDateFormat sdf = (SimpleDateFormat) df;
sdf.setDateFormatSymbols(dfs);

Date jud = new SimpleDateFormat("yyyy-MM-dd").parse("2014-02-28");
String month = sdf.format(jud);
System.out.println(month); // output: 28 февраля 2014 г.

Joda-Time does not offer a good solution in a Java-pre-8 environment because it only delegates to JDK. See also a similar issue on Joda-site.

Finally there is also my library Time4J which can solve the problem like Java-8, but uses its own text resources for Russian and understands both forms (old style and standalone-style), so this is a simple solution for older Java-versions (and will of course not be obsoleted by Java-8 due to many other feature enhancements).

System.out.println(
    ChronoFormatter.ofDateStyle(DisplayMode.FULL, new Locale("ru")).format(
        PlainDate.of(2014, Month.FEBRUARY, 28)
    )
); // output: 28 февраля 2014 г.

For Java 8 you can use a new pattern.

In short: The "LLLL" pattern will get a Nominative case:

new SimpleDateFormat("LLLL", Locale.getDefault()).format(date); // январь

The "MMMM" pattern will return a String in Genitive case:

new SimpleDateFormat("MMMM", Locale.getDefault()).format(date); // января

Alternatively, instead of hardcoding Russian months in array (since we have Polish, Ukrainian and other languages), you could use the java.time.Month enum. It contains both months int number and String name.