Различные форматы даты

У меня возникла проблема при преобразовании даты в моем приложении для Android. Моя проблема в том, что у меня есть два разных формата даты.

SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy");
DateFormat formatter_date = new SimpleDateFormat("dd.MMM.yyyy");
Date myDate = null;
try {
    myDate = dateFormat.parse("28.10.2015");
} catch (ParseException e) {
    e.printStackTrace();
}
formatter_date.format(myDate,"dd.MM.yyyy"))
txtDate.setText(formatter_date.format(myDate,"dd.MM.yyyy")));

Я хочу, чтобы дата была отформатирована как 28 октября 2015 года на устройстве, настроенном на английский язык, как 28 октября 2015 года на немецком языке и т. д. Поэтому всегда одна точка до и после аббревиатуры месяца. Когда установлен английский язык, возвращается 28 октября 2015 г., как и должно быть, однако, когда установлен немецкий язык, возвращается 28 октября..2015 с двумя точками между окт. em> и 2015.

Есть ли какое-либо решение для обработки этого?


person Franzi    schedule 19.01.2018    source источник
comment
В качестве отступления подумайте о том, чтобы выбросить давно устаревший и заведомо неприятный SimpleDateFormat и друзей и добавить ThreeTenABP на свой Android. проект, чтобы использовать java.time, современный API даты и времени Java. С ним намного приятнее работать.   -  person Ole V.V.    schedule 20.01.2018
comment
Какой результат вы хотите?   -  person Ole V.V.    schedule 20.01.2018
comment
Стандартная дата в формате дд.МММ.гггг для всех возможных языковых настроек (День.3Буквы Месяц.Год)   -  person Franzi    schedule 20.01.2018
comment
У меня какие-то неправильные настройки или почему в немецком переводе между месяцем и годом стоят две точки?   -  person Franzi    schedule 20.01.2018
comment
А, этого я не заметил. В немецком языке (как вы, несомненно, знаете) точка используется как аббревиатура, поэтому краткая форма Oktober будет Okt. с точкой. В английском языке точка иногда используется для аналогичной цели, но она не используется с краткой формой названия месяца, поэтому октябрь становится октябрь без точки. Я не вижу простого способа обойти это.   -  person Ole V.V.    schedule 20.01.2018
comment
Я надеялся, что встроенные локализованные форматы хотя бы сблизят вас, но нет. Длинный немецкий формат — 28 октября 2015 г., а средний формат — 28.10.2015. Никто не дает вам трехбуквенную аббревиатуру месяца.   -  person Ole V.V.    schedule 20.01.2018
comment
Во многих языках месяцы июнь и июль начинаются с одних и тех же трех букв, включая северо-фризский (juuni, juuli) и французский (juin, juillet). Вы можете подумать еще раз. См. месяцы года на разных языках.   -  person Ole V.V.    schedule 20.01.2018


Ответы (3)


Я хотел бы оспорить то, о чем вы просите. Конечно, вы можете его получить, как уже показывает ваш собственный ответ. Но хочешь ли ты этого?

Используйте встроенные локализованные форматы

В Java есть локализованные форматы для всех доступных локалей (думаю всех, во всяком случае их много). Я предлагаю вам использовать их, а не ваше собственное представление о том, как должна выглядеть локализованная дата. В то время как 28.Okt.2015, вероятно, является обычным явлением в Австрии и других немецкоязычных странах, англоязычные люди не привыкли к точкам в вашем формате, и я подозреваю, что некоторые люди в мире сочтут это более или менее странным.

В комментарии я предложил вам добавить ThreeTenABP в свой проект Android, чтобы использовать java.time, современный API даты и времени Java. С ним намного приятнее работать. Теперь я принимаю свое лекарство:

    DateTimeFormatter dateFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);
    LocalDate myDate = LocalDate.of(2015, Month.OCTOBER, 28);
    System.out.println(myDate.format(dateFormatter));

Вывод в разных локалях включает:

German:     28.10.2015
UK English: 28 Oct 2015
French:     28 oct. 2015

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

Изменить: откуда взялась LocalDate?

Я понял, что вы конвертировали из строки типа "28.10.2015". Преобразовать это в LocalDate просто, если вы знаете, как это сделать:

    DateTimeFormatter numericDateFormatter = DateTimeFormatter.ofPattern("dd.MM.uuuu");
    LocalDate myDate = LocalDate.parse("28.10.2015", numericDateFormatter);

Только если вы получили java.util.Date из устаревшего API, который вы не можете изменить или не хотите менять прямо сейчас, сначала преобразуйте его в современный тип Instant и выполните дальнейшие преобразования оттуда:

    LocalDate myDate = oldfashionedJavaUtilDate.toInstant()
            .atZone(ZoneId.of("Europe/Vienna"))
            .toLocalDate();

Поскольку это чувствительная к часовому поясу операция, я рекомендую указать явный часовой пояс. Вы можете использовать настройку часового пояса JVM, указав ZoneId.systemDefault(), но имейте в виду, что это ненадежно: настройка JVM может быть изменена под вашими ногами другими частями вашей программы или другими программами, работающими в той же JVM.

Что вы просили

Версия java.time того, что вы просили, очень похожа на код в вашем собственном ответе:

    DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd");
    DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern("MMMM");
    DateTimeFormatter yearFormatter = DateTimeFormatter.ofPattern("uuuu");
    LocalDate myDate = LocalDate.of(2015, Month.OCTOBER, 28);
    String dayOfMonth = myDate.format(dateFormatter);
    String monthName = myDate.format(monthFormatter);
    if (monthName.length() > 3) {
        monthName = monthName.substring(0, 3);
    }
    String year = myDate.format(yearFormatter);
    String formattedDate = dayOfMonth + '.' + monthName + '.' + year;
    System.out.println(formattedDate);

Вывод в тех же локалях, что и выше:

German:     28.Okt.2015
UK English: 28.Oct.2015
French:     28.oct.2015

Однако есть гораздо более короткий способ получить то же самое:

    String formattedDate = String.format("%1$td.%2$.3s.%1$tY", 
            myDate,
            myDate.getMonth().getDisplayName(TextStyle.FULL, Locale.getDefault()));

Читать сложнее. Мне потребовалось несколько попыток, чтобы форматировать строку %1$td.%2$.3s.%1$tY точно правильно. И тех, кто поддерживает ваш код, удивит, если они привыкли к DateTimeFormatter для форматирования даты (и времени). Так что я не очень рекомендую это, но выбор за вами.

С другой датой я получил следующий вывод на французском языке:

08.jui.2018

Ни франкоязычный человек, ни кто-либо еще в этом отношении не будет знать, была ли эта дата в июне (juin) или в июле (juillet). В 57 доступных локалях моей JVM все 12 месяцев года начинаются с одних и тех же трех букв. Такие языки включают тибетский, суахили, сомалийский, корнуоллский, шотландский гэльский и вьетнамский языки. В этих языках никто не сможет отличить месяцы друг от друга. Пожалуйста, подумайте дважды.

Ссылки

person Ole V.V.    schedule 20.01.2018
comment
Отличный совет, чтобы позволить java.time автоматически локализовать для вас. - person Basil Bourque; 21.01.2018
comment
Здравствуйте, спасибо за вашу информацию, но как я могу получить дату объекта в LocalDate? - person Franzi; 29.01.2018
comment
@Franzi, я отредактировал. Если я не понял ваш вопрос так, как вы его хотели, пожалуйста, вернитесь. - person Ole V.V.; 29.01.2018

SimpleDateFormat dateFormat = new SimpleDateFormat(String pattern, Locale locale);

имеет другой конструктор с Locale изменением Locale.ENGLISH для установки даты на английском языке. Вы можете проверить другие параметры локали. Обычно я использую Locale.getDefault() для отображения даты на предпочитаемом пользователем языке.

person Thracian    schedule 19.01.2018

Спасибо за помощь, но это решение работает лучше всего для меня

 DateFormat formatter_month = new SimpleDateFormat("MMMM"); //Get Whole Name of Month
 DateFormat formatter_day = new SimpleDateFormat("dd."); //Get Day + Dot(2 digits)
 DateFormat formatter_year = new SimpleDateFormat(".yyyy"); //Get Dot + Year(4 digits)
 String str_date = formatter_day.format(date)+  //Day
 formatter_month.format(date).substring(0,3)+   //Month
 formatter_year.format(date);   //Year
person Franzi    schedule 20.01.2018
comment
Хорошо, что вы нашли решение. Учтите, что название месяца уже может быть короче трех букв. На креольском языке май означает я. Вы вряд ли найдете устройство с языком Sercquiais, но если найдете, август будет u, всего одна буква. - person Ole V.V.; 20.01.2018
comment
К вашему сведению, неприятные старые классы даты и времени, такие как java.util.Date , java.util.Calendar и java.text.SimpleDateFormat теперь являются устаревшими, вытесненными java.time, встроенные в Java 8 и Java 9. См. Учебник Oracle. - person Basil Bourque; 21.01.2018