Правильный перевод строки в русском языке Java

Я хочу преобразовать дату на русский и использовать код ниже

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

где locale имеет тип Locale Проблема в том, что месяцы не обрабатываются правильно. Январь идет как "январь", он должен быть "января", а февраль идет как "февраль" должен быть "февраля"

и т.д.

Одна из идей - преобразовать неправильные месяцы в правильные в моей логике

Есть ли какие-либо вещи, с помощью которых Java делает это автоматически?

Спасибо

Ответ 1

В моей JDK-6 -установке я могу воспроизвести вашу проблему:

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 предлагает вам решение.

Кажется, что JDK изменил внутренний дефолт с "автономного стиля" (номинативный) на "формат-стиль" (родительный падеж).

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

Если вам нужно применить автономный текстовый стиль, вам нужно настроить свой собственный DateTimeFormatterBuilder, который требует немного больше усилий, иначе TextStyle.FULL должен быть по умолчанию.

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)

Обходной путь для Java-pre-8 с использованием старого стиля:

Определите свои собственные текстовые ресурсы (хлопотно)!

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 не предлагает хорошего решения в среде Java-pre-8, потому что он делегирует только JDK. См. Также аналогичную проблему на сайте Joda.

Наконец, есть также моя библиотека Time4J, которая может решить проблему вроде Java-8, но использует собственные текстовые ресурсы для Русский и понимает обе формы (старый стиль и автономный стиль), поэтому это простое решение для старых Java-версий (и, конечно же, не будет устаревать Java-8 из-за многих других улучшений функций).

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

Ответ 2

Для Java 8 вы можете использовать новый шаблон.

Вкратце: Образец "LLLL" получит номинальный случай:

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

Образец "MMMM" вернет String в родительном случае:

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

В качестве альтернативы вместо жесткого кодирования русских месяцев в массиве (поскольку у нас есть языки на польском, украинском и других языках), вы можете использовать перечисление java.time.Month. Он содержит как месяцы int, так и String.

Ответ 3

AFAIK, нет поддержки локализации в винительном падеже в JDK. Я бы предложил использовать формат даты MEDIUM для работы, если это подходит: 15 Фев 1999

В противном случае вам может потребоваться предоставить ваши собственные локализации для имен месяцев.

Ответ 4

Хотя принятый ответ @Meno Hochschild и fooobar.com/questions/549688/... верны, я хочу добавить немного.

Достаточно установить Locale("ru"), затем создать и применить sdf.format(date).

public static String formatDate(long date, String format) {
    Locale locale = new Locale("ru");
    SimpleDateFormat sdf = new SimpleDateFormat(format, locale);
    return sdf.format(date);
}

Но если вы хотите настроить его, я покажу процесс.

После многих исключений я понял, что будние дни начинаются не с понедельника (см. http://jexp.ru/index.php/Java_Tutorial/Data_Type/Date_Format#Change_date_formatting_symbols)!

public static String formatDate(long date, String format) {
    //Locale locale = new Locale("fr");
    Locale locale = new Locale("ru");
    DateFormatSymbols dfs = DateFormatSymbols.getInstance(locale);
    String[] months = {
            "января", "февраля", "марта", "апреля", "мая", "июня",
            "июля", "августа", "сентября", "октября", "ноября", "декабря"};
    String[] shortMonths = {
            "янв", "фев", "мар", "апр", "май", "июн",
            "июл", "авг", "сен", "окт", "ноя", "дек"};
    dfs.setMonths(months);
    dfs.setShortMonths(shortMonths);
    String[] weekdays = {"", "Воскресенье", "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота"};
    String[] shortWeekdays = {"", "вс", "пн", "вт", "ср", "чт", "пт", "сб"};
    dfs.setWeekdays(weekdays);
    dfs.setShortWeekdays(shortWeekdays);

    SimpleDateFormat sdf = new SimpleDateFormat(format, locale);
    sdf.setDateFormatSymbols(dfs);
    return sdf.format(date); // пт, 09 декабря 2016
}

Ответ 5

Извините, если мой ответ не будет полностью соответствовать этому вопросу, но все же "Я хотел бы поделиться своим путем решения проблемы с переводом даты в русский формат.

У вас была большая головная боль при работе с DateTime Locales и т.д., я начал просто переводить дни недели и месяцы в строковое представление исходной даты.

String originalDate = "Tue, 22 Nov 2016 01:03:00 +0300";
Log.d("Date in Russian",convertStringDateToRussian(linkText));

public String convertStringDateToRussian(String mDate) {

    String[] engWeek = {
            "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
            "Sun"};
    String[] ruWeek = {
            "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота",
            "Воскресенье"};
    String[] engMonths = {
            "Jan", "Feb", "Mar", "Apr", "May", "Jun",
            "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
    String[] ruMonths = {
            "января", "февраля", "марта", "апреля", "мая", "июня",
            "июля", "августа", "сентября", "октября", "ноября", "декабря"};
    for (
            int t = 0;
            t < engWeek.length; t++)

    {
        if (mDate.contains(engWeek[t])) {
            mDate = mDate.replace(engWeek[t], ruWeek[t]);
            break;
        }
    }

    for (
            int t = 0;
            t < engMonths.length; t++)

    {
        if (mDate.contains(engMonths[t])) {
            mDate = mDate.replace(engMonths[t], ruMonths[t]);
            break;
        }
    }

    return mDate;
}