Bezdepbonusu7Программирование: статьи и ответы

Вопрос

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

Автор вопроса: FranziОтветов: 3

У меня возникла проблема при преобразовании даты в моем приложении для 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.

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

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

androiddatedate-formatsimpledateformat

Ответы

Ответ 1 · рейтинг 2 · Ole V.V.

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

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

В 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 месяцев года начинаются с одних и тех же трех букв. Такие языки включают тибетский, суахили, сомалийский, корнуоллский, шотландский гэльский и вьетнамский языки. В этих языках никто не сможет отличить месяцы друг от друга. Пожалуйста, подумайте дважды.

Ссылки

Ответ 2 · рейтинг 1 · Thracian

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

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

Ответ 3 · Franzi

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

 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

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы