Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper Russian month string translation Java

I want to convert a Date in to Russian and using the code below

SimpleDateFormat.getDateInstance(SimpleDateFormat.LONG,locale).format(date);

where locale is of type Locale The problem is months are not parsed correctly . January is coming as "январь" it should be "января" and February is coming as "февраль" should be "февраля"

and so on...

One idea is to convert incorrect months to proper ones in my logic

Is there any thing by which Java do this automatically ?

Thanks

like image 293
abhig Avatar asked Oct 29 '14 23:10

abhig


2 Answers

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 г.
like image 80
Meno Hochschild Avatar answered Sep 22 '22 20:09

Meno Hochschild


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.

like image 28
Vitalii Dmitriev Avatar answered Sep 20 '22 20:09

Vitalii Dmitriev