Вывод дневного периода на основе локали - PullRequest
0 голосов
/ 10 декабря 2018

Я хочу отформатировать дату, которая должна быть локализована и включает «дневной период».

«Дневной период» означает не am / pm, а «полдень», «раннее утро» и т. Д.

Форматированная дата, основанная на немецкой локали с включенной настройкой 12 часов, должна выглядеть как 03.08.18, 9:01 abends, «abends» означает вечер.

Тот же самый пример должен быть 3/8/18 9:01 de la noche на испанском языке. Почему я думаю, что это возможно :

A: Потому что даты в приложении Android для WhatsApp форматируются следующим образом

B: Поскольку исходный код Java 10 включает в себя следующее (изфайл немецкого перевода):

<dayPeriods>
<dayPeriodContext type="format">
    <dayPeriodWidth type="wide">
        <dayPeriod type="afternoon">nachmittags</dayPeriod>
        <dayPeriod type="am">vorm.</dayPeriod>
        <dayPeriod type="earlyMorning">morgens</dayPeriod>
        <dayPeriod type="evening">abends</dayPeriod>
        <dayPeriod type="morning">vormittags</dayPeriod>
        <dayPeriod type="night">nachts</dayPeriod>
        <dayPeriod type="noon">Mittag</dayPeriod>
        <dayPeriod type="pm">nachm.</dayPeriod>
    </dayPeriodWidth>
</dayPeriodContext>
...
</dayPeriods>

Я пытался : (текущая локаль)

DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, current);

String formattedDate = df.format(System.currentTimeMillis());

Вывод: 08.12.18 7:24 nachm или 8/12/18 7:54 p. m.Следующий код имеет такой же вывод:

DateFormat abc = SimpleDateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, current);

abc.format(System.currentTimeMillis());

Я также попробовал DateTimeFormatterBuilder (со всеми версиями AMPM_OF_DAY):

DateTimeFormatter test = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.SHORT);

DateTimeFormatter fmt = new DateTimeFormatterBuilder()
                .append(test)
                .appendText(ChronoField.AMPM_OF_DAY, TextStyle.SHORT)
                .appendText(ChronoField.AMPM_OF_DAY, TextStyle.NARROW)
                .appendText(ChronoField.AMPM_OF_DAY, TextStyle.FULL)
                .appendText(ChronoField.AMPM_OF_DAY, TextStyle.FULL_STANDALONE)
                .toFormatter(current);

ZonedDateTime date = ZonedDateTime.now();
date.format(fmt);

Вывод: 8 dic. 2018 19:54p. m.p. m.p. m.11

Есть ли способ вывести дату таким образом?

Спасибо

1 Ответ

0 голосов
/ 10 декабря 2018

Есть только две библиотеки, которые поддерживают дневные периоды, а именно ICU4J (частично встроенный в Android) и мою библиотеку Time4A.Другие средства форматирования, такие как java.text.DateFormat или java.time.format.DateTimeFormatter, не поддерживают.

Пример в Time4A для немецкой локали (здесь с мостом к старомодному типу java.util.Date):

 ChronoFormatter<java.util.Date> f =
      ChronoFormatter.ofPattern(
          "dd.MM.uuuu, h:mm BBBB",
          PatternType.CLDR,
          Locale.GERMAN,
          Moment.axis(TemporalType.JAVA_UTIL_DATE))
      .withStdTimezone();
 System.out.println(f.format(new java.util.Date()));

пример выходных данных => "11.12.2018, 6:03 morgens"

Используется специальный символ "B" , определенный LDML-синтаксисом CLDR-данные (управляются консорциумом Unicode).Правила дневного разбиения также взяты из данных CLDR и выглядят по-немецки как:

# day-period-rules
T0000=night1
T0500=morning1
T1000=morning2
T1200=afternoon1
T1300=afternoon2
T1800=evening1

# day-period-translations
P(a)_morning1=morgens
P(a)_morning2=vormittags
P(a)_afternoon1=mittags
P(a)_afternoon2=nachmittags
P(a)_evening1=abends
P(a)_night1=nachts

Если вы не согласны с этими данными, вы можете создать свой собственный настраиваемый форматер с помощью шаблона builder .

Примечание по ICU4J: я не тестировал эту библиотеку, но, возможно, ее класс com.ibm.icu.text.SimpleDateFormat также поддерживает символ шаблона B (но тогда javadoc устарел).

Еще одно примечание:

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

    Locale loc = Locale.US;

    // our concrete values to be formatted
    Moment moment = SystemClock.currentMoment();
    PlainDate calendarDate = moment.toLocalTimestamp().getCalendarDate();

    // get the localized clock pattern
    Map<String, String> textForms = CalendarText.getIsoInstance(loc).getTextForms();
    String pattern = 
            textForms.containsKey("F_Bhm") ? textForms.get("F_Bhm") : "h:mm B";

    // construct the style-based date formatter
    ChronoFormatter<PlainDate> f1 = 
            ChronoFormatter.ofDateStyle(DisplayMode.SHORT, loc);

    // construct the time formatter
    ChronoFormatter<Moment> f2 = ChronoFormatter.ofMomentPattern(
        pattern,
        PatternType.CLDR,
        loc,
        Timezone.ofSystem().getID());

    System.out.println(f1.format(calendarDate) + " " + f2.format(moment));
    // example output => "12/11/18 6:18 in the morning"
...