Подтвердить что ты не робот

Как получить локализованную строку шаблона даты?

Очень легко форматировать и анализировать классы Java Date (или Calendar), используя экземпляр DateFormat, то есть я мог форматировать текущую дату в короткую локализованную дату:

DateFormat formatter = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault());
String today = formatter.format(new Date());

Моя проблема: мне нужно получить эту локализованную строку шаблона (например, что-то вроде "MM/dd/yy"). Это должно быть тривиальной задачей, но я просто не мог найти поставщика...

4b9b3361

Ответ 1

Для SimpleDateFormat вы вызываете toLocalizedPattern()

EDIT:

Для пользователей Java 8:

API-интерфейс Java 8 Date Time похож на Joda-time. Чтобы получить локализованный шаблон, мы можем использовать класс DateTimeFormatter

DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);

Обратите внимание, что когда вы вызываете toString() в LocalDate, вы получите дату в формате ISO-8601

Обратите внимание, что API Time Time в Java 8 вдохновлен Joda Time, и большинство решений могут основываться на вопросах, связанных с временем.

Ответ 2

Для тех, кто по-прежнему использует Java 7 и старше:

Вы можете использовать что-то вроде этого:

DateFormat formatter = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault());
String pattern       = ((SimpleDateFormat)formatter).toPattern();
String localPattern  = ((SimpleDateFormat)formatter).toLocalizedPattern();

Так как DateFormat, возвращаемый From getDateInstance(), является экземпляром SimpleDateFormat. Эти два метода действительно должны быть в DateFormat, чтобы это было менее хаки, но в настоящее время они не являются.

Ответ 3

Возможно, странно, что я отвечаю на свой вопрос, но я верю, что могу добавить что-то к картине.

Внедрение ICU

Очевидно, что Java 8 дает вам много, но есть и еще что-то: ICU4J. На самом деле это источник оригинальной реализации Java таких вещей, как Calendar, DateFormat и SimpleDateFormat, чтобы назвать несколько.
Поэтому не должно быть неожиданностью, что ICU SimpleDateFormat также содержит методы, такие как toPattern() или toLocalizedPattern(). Вы можете увидеть их в действии здесь:

DateFormat fmt = DateFormat.getPatternInstance(
        DateFormat.YEAR_MONTH,
        Locale.forLanguageTag("pl-PL"));

if (fmt instanceof SimpleDateFormat) {
    SimpleDateFormat sfmt = (SimpleDateFormat) fmt;
    String pattern = sfmt.toPattern();
    String localizedPattern = sfmt.toLocalizedPattern();
    System.out.println(pattern);
    System.out.println(localizedPattern);
}

усовершенствования ICU

Это ничего нового, но я хотел бы отметить это:

DateFormat.getPatternInstance(String pattern, Locale locale);

Это метод, который может возвращать целую кучу специфичных для локали шаблонов, таких как:

  • ABBR_QUARTER
  • КВАРТАЛ
  • год
  • YEAR_ABBR_QUARTER
  • YEAR_QUARTER
  • YEAR_ABBR_MONTH
  • YEAR_MONTH
  • YEAR_NUM_MONTH
  • YEAR_ABBR_MONTH_DAY
  • YEAR_NUM_MONTH_DAY
  • YEAR_MONTH_DAY
  • YEAR_ABBR_MONTH_WEEKDAY_DAY
  • YEAR_MONTH_WEEKDAY_DAY
  • YEAR_NUM_MONTH_WEEKDAY_DAY
  • ABBR_MONTH
  • МЕСЯЦ
  • NUM_MONTH
  • ABBR_STANDALONE_MONTH
  • STANDALONE_MONTH
  • ABBR_MONTH_DAY
  • MONTH_DAY
  • NUM_MONTH_DAY
  • ABBR_MONTH_WEEKDAY_DAY
  • MONTH_WEEKDAY_DAY
  • NUM_MONTH_WEEKDAY_DAY
  • ДЕНЬ
  • ABBR_WEEKDAY
  • WEEKDAY
  • ЧАС
  • HOUR24
  • HOUR_MINUTE
  • HOUR_MINUTE_SECOND
  • HOUR24_MINUTE
  • HOUR24_MINUTE_SECOND
  • HOUR_TZ
  • HOUR_GENERIC_TZ
  • HOUR_MINUTE_TZ
  • HOUR_MINUTE_GENERIC_TZ
  • МИНУТА
  • MINUTE_SECOND
  • ВТОРОЕ
  • ABBR_UTC_TZ
  • ABBR_SPECIFIC_TZ
  • SPECIFIC_TZ
  • ABBR_GENERIC_TZ
  • GENERIC_TZ
  • LOCATION_TZ

Конечно, их немало. Что хорошо в них, так это то, что эти шаблоны фактически являются строками (как в java.lang.String), то есть, если вы используете английский шаблон "MM/d", вы получите обратную привязку к языку. Это может быть полезно в некоторых случаях. Обычно вы просто используете экземпляр DateFormat и не будете заботиться о самом шаблоне.

Локально-специфичный шаблон против локализованного шаблона

Задача заключалась в том, чтобы получить локализацию, а не шаблон, специфичный для локали. Какая разница?

В теории, toPattern() даст вам специфичный для локали шаблон (в зависимости от Locale, который вы использовали для создания экземпляра (Simple)DateFormat). То есть независимо от того, какой целевой язык/страна вы положили, вы получите шаблон, составленный из таких символов, как y, M, d, h, h, M и т.д.

С другой стороны, toLocalizedPattern() должен возвращать локализованный шаблон, это то, что подходит для конечных пользователей для чтения и понимания. Например, немецкий шаблон даты (по умолчанию):

  • toPattern(): dd.MM.yyyy
  • toLocalizedPattern(): tt.MM.jjjj(day = Tag, month = Monat, year = Jahr)

Цель вопроса заключалась в следующем: "как найти локализованный шаблон, который может служить подсказкой о том, какой формат даты/времени". То есть, скажем, у нас есть поле даты, которое пользователь может заполнить, используя шаблон, специфичный для локали, но я хочу отобразить подсказку формата в локализованной форме.

К сожалению, до сих пор нет хорошего решения. Я уже упоминал ранее в этом сообщении ICU. Это потому, что данные, которые использует ICU, поступают из CLDR, что, к сожалению, частично переведено/частично исправлено. В случае моего родного языка, на момент написания, ни шаблоны, ни их локализованные формы не были правильно переведены. И каждый раз, когда я их исправляю, меня обманывали другие люди, которым не нужно жить в Польше, и не говорят на польском языке...

Мораль этой истории: не полностью полагаться на CLDR. Вам все еще нужно иметь локальных аудиторов/лингвистических обозревателей.

Ответ 4

Вы можете использовать DateTimeFormatterBuilder в Java 8. В следующем примере возвращается шаблон с локализованной датой, например. "d.M.yyyy".

String datePattern = DateTimeFormatterBuilder.getLocalizedDateTimePattern(
  FormatStyle.SHORT, null, IsoChronology.INSTANCE, 
  Locale.GERMANY); // or whatever Locale

Ответ 5

Следующий код даст вам шаблон для локали:

final String pattern1 = ((SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, locale)).toPattern();
System.out.println(pattern1);

Ответ 6

Java 8 предоставляет некоторые полезные функции для работы с датой и временем форматирования/синтаксического анализа, включая обработку локалей. Вот краткое введение.

Основные шаблоны

В простейшем случае для форматирования/анализа даты вы использовали бы следующий код с шаблоном String:

DateTimeFormatter.ofPattern("MM/dd/yyyy")

Стандарт затем должен использовать это с объектом даты непосредственно для форматирования:

return LocalDate.now().format(DateTimeFormatter.ofPattern("MM/dd/yyyy"));

И затем используя шаблон factory для синтаксического анализа даты:

return LocalDate.parse(dateString, DateTimeFormatter.ofPattern("MM/dd/yyyy"));

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

Locales

Включение локали довольно просто: для языкового стандарта по умолчанию у вас есть следующие параметры, которые затем могут быть применены к параметрам форматирования/анализа, показанным выше:

DateTimeFormatter.ofLocalizedDate(dateStyle);

Параметр 'dateStyle' выше FormatStyle параметр Enum для представления полной, длинной, средней и короткой версий локализованной даты, когда работая с DateTimeFormatter. Используя FormatStyle, у вас также есть следующие опции:

DateTimeFormatter.ofLocalizedTime(timeStyle);
DateTimeFormatter.ofLocalizedDateTime(dateTimeStyle);
DateTimeFormatter.ofLocalizedDateTime(dateTimeStyle, timeStyle);

Последняя опция позволяет вам указать другую FormatStyle для даты и времени. Если вы не работаете с Locale по умолчанию, возврат каждого из методов Localized можно настроить с помощью опции .withLocale, например,

DateTimeFormatter.ofLocalizedTime(timeStyle).withLocale(Locale.ENGLISH);

Кроме того, у параметраPattern есть перегруженная версия, чтобы указать язык тоже

DateTimeFormatter.ofPattern("MM/dd/yyyy",Locale.ENGLISH);

Мне нужно больше!

DateTimeFormatter будет соответствовать большинству вариантов использования, однако он построен на DateTimeFormatterBuilder, который предоставляет пользователю огромный выбор опций строителя. Используйте DateTimeFormatter для начала, и если вам нужны эти расширенные функции форматирования, возвращайтесь к строителю.

Ответ 7

Поскольку это только информация о локали, которую вы используете, я думаю, что вам нужно будет найти файл, который JVM (OpenJDK или Harmony) фактически использует в качестве входных данных для всего объекта Locale и выясняет, как разобрать его. Или просто используйте другой источник в Интернете (наверняка там есть список). Это спасет этих бедных переводчиков.

Ответ 8

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

 public static String getLocaleDatePattern(Locale locale) {
    // Validating if Locale instance is null
    if (locale == null || locale.getLanguage() == null) {
        return "MM/dd/yyyy";
    }
    // Fetching the locale specific date pattern
    String localeDatePattern = ((SimpleDateFormat) DateFormat.getDateInstance(
            DateFormat.SHORT, locale)).toPattern();
    // Validating if locale type is having language code for Chinese and country 
    // code for (Hong Kong) with Date Format as - yy'?'M'?'d'?'
    if (locale.toString().equalsIgnoreCase("zh_hk")) {
        // Expected application Date Format for Chinese (Hong Kong) locale type
        return "yyyy'MM'dd";
    }
    // Replacing all d|m|y OR Gy with dd|MM|yyyy as per the locale date pattern
    localeDatePattern = localeDatePattern.replaceAll("d{1,2}", "dd").replaceAll(
            "M{1,2}", "MM").replaceAll("y{1,4}|Gy", "yyyy");
    // Replacing all blank spaces in the locale date pattern
    localeDatePattern = localeDatePattern.replace(" ", "");
    // Validating the date pattern length to remove any extract characters
    if (localeDatePattern.length() > 10) {
        // Keeping the standard length as expected by the application
        localeDatePattern = localeDatePattern.substring(0, 10);
    }
    return localeDatePattern;
}

Ответ 9

Вы можете попробовать что-то вроде:

LocalDate fromCustomPattern = LocalDate.parse("20.01.2014", DateTimeFormatter.ofPattern("MM/dd/yy"))

Ответ 10

Я не уверен, что вы хотите, но...

Пример SimpleDateFormat:

SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yy");
Date date = sdf.parse("12/31/10");
String str = sdf.format(new Date());