Локализованные форматы даты и времени в Java

Начиная с JDK 8, у нас есть комплексный API даты и времени, содержащий такие классы, как LocalDate, LocalTime, LocalDateTime, ZonedDateTime, OffsetDateTime и OffsetTime. Эти классы позволяют легко форматировать вывод даты и времени с помощью DateTimeFormatter.ofPattern(). API также позволяет дополнительно настраивать вывод на основе указанной информации о локали для поддержки функций локализации и интернационализации.

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

1. Отображение даты и времени в формате, соответствующем региону

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

  • Получить текущую локаль пользователя. Если информация о локали не представлена, использовать локаль по умолчанию.
  • Используйте информацию о локали для создания объекта DateTimeFormatter.
  • Используйте DateTimeFormatter.format() для вывода даты и времени в зависимости от локали.
Locale locale = Locale.forLanguageTag("es");DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).withLocale(locale);String formattedDate = formatter.format( ZonedDateTime.now() );System.out.println(formattedDate); // Prints '14 ene 2024, 8:09:47'

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

Мы можем использовать методы ofLocalizedDate(), ofLocalizedTime() и ofLocalizedDateTime(), чтобы получить определенные части даты и времени, отформатированные с использованием правил локали.

Locale.setDefault(Locale.GERMANY);String ld = LocalDate.now().format(DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG));System.out.println(ld); // 14. Januar 2024String lt = LocalTime.now().format(DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT));System.out.println(lt); // 08:14String ldt = LocalDateTime.now().format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM));System.out.println(ldt); // 14.01.2024, 08:14:25

2. Получение локали пользователя

Обратите внимание, что получение информации о текущей локали различается в зависимости от приложения и фреймворка.

Например, мы можем использовать AcceptHeaderLocaleResolver в веб-приложении Spring, которое использует основную локаль, указанную в заголовке «Accept-language» HTTP-запроса(локаль, отправленная клиентским браузером, обычно локаль клиентской ОС).

@Beanpublic LocalResolver localeResolver() {AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();localeResolver.setSupportedLocales(Arrays.asList(new Locale("fa"), new Locale("en")));localeResolver.setDefaultLocale(new Locale("fa"));return localeResolver;}

Чтобы получить языковой тег, специфичный для локали, используйте вызов метода LocaleContextHolder.getLocale().

3. Использование ofLocalizedPattern() начиная с Java 19

Начиная с JDK 19, мы можем использовать метод ofLocalizedPattern(String pattern) для создания локале-специфичного DateTimeFormatter, полученного из указанного шаблона. Мы можем передать любой шаблон, который соблюдает хронологию ISO, указанную ниже:

"G{0,5}" + // Era"y*" + // Year"Q{0,5}" + // Quarter"M{0,5}" + // Month"w*" + // Week of Week Based Year"E{0,5}" + // Day of Week"d{0,2}" + // Day of Month"B{0,5}" + // Period/AmPm of Day"[hHjC]{0,2}" + // Hour of Day/AmPm(refer to LDML for 'j' and 'C')"m{0,2}" + // Minute of Hour"s{0,2}" + // Second of Minute"[vz]{0,4}" // Zone

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

Locale.setDefault(Locale.ENGLISH);String ld1 = LocalDate.now().format(DateTimeFormatter.ofLocalizedPattern("yMM"));System.out.println(ld1); // 1/2024String ld2 = LocalDate.now().format(DateTimeFormatter.ofLocalizedPattern("yMMM"));System.out.println(ld2); // Jan 2024

4. Заключение

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

Если вы хотите изменить значения даты и времени для заданного часового пояса, то используйте DateTimeFormatter.withZone(zoneId).

Исходный код на Github

Прокрутить вверх