Руководство по DateTimeFormatter

Руководство по DateTimeFormatter

1. обзор

В этом руководстве мы рассмотрим класс Java 8DateTimeFormatter и его шаблоны форматирования.. Мы также собираемся обсудить возможные варианты использования этого класса.

Мы можем использоватьDateTimeFormatter для единообразного форматирования даты и времени в приложении с помощью предопределенных или определяемых пользователем шаблонов.

2. DateTimeFormatter с предопределенными экземплярами

DateTimeFormatter comes with multiple predefined date/time formats , которые соответствуют стандартам ISO и RFC. Например, мы можем использовать экземплярISO_LOCAL_DATE для анализа даты, такой как «2018-03-09»:

DateTimeFormatter.ISO_LOCAL_DATE.format(LocalDate.of(2018, 3, 9));

Чтобы проанализировать дату со смещением, мы можем использоватьISO_OFFSET_DATE, чтобы получить результат вроде «2018-03-09-03: 00»:

DateTimeFormatter.ISO_OFFSET_DATE.format(LocalDate.of(2018, 3, 9).atStartOfDay(ZoneId.of("UTC-3")));

Most of the predefined instances of the DateTimeFormatter class are focused on the ISO-8601 standard. ISO-8601 - это международный стандарт форматирования даты и времени.

Однако существует один другой предопределенный экземпляр, который анализирует RFC-1123, Требования к Интернет-хостам,published, подготовленный IETF:

DateTimeFormatter.RFC_1123_DATE_TIME.format(LocalDate.of(2018, 3, 9).atStartOfDay(ZoneId.of("UTC-3")));

Этот фрагмент кода генерирует "Fri, 9 Mar 2018 00:00:00 -0300".

Иногда нам приходится манипулировать датой, которую мы получаем какString известного формата. Мы можем использовать методparse():

LocalDate.from(DateTimeFormatter.ISO_LOCAL_DATE.parse("2018-03-09")).plusDays(3);

Результатом этого фрагмента кода является представлениеLocalDate за 12 марта 2018 г.

3. DateTimeFormatter сFormatStyle

Иногда мы можем захотеть напечатать даты понятным для человека способом.

В таких случаях мы можем использовать значения перечисленияjava.time.format.FormatStyle (FULL, LONG, MEDIUM, SHORT) с нашимиDateTimeFormatter:

LocalDate anotherSummerDay = LocalDate.of(2016, 8, 23);
System.out.println(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).format(anotherSummerDay));
System.out.println(DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG).format(anotherSummerDay));
System.out.println(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).format(anotherSummerDay));
System.out.println(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).format(anotherSummerDay));

Вывод этих различных стилей форматирования одной и той же даты:

Tuesday, August 23, 2016
August 23, 2016
Aug 23, 2016
8/23/16

Мы также можем использовать предопределенные стили форматирования для даты и времени. Чтобы использоватьFormatStyle со временем, нам нужно будет использовать экземплярZonedDateTime, иначе будет выданDateTimeException:

LocalDate anotherSummerDay = LocalDate.of(2016, 8, 23);
LocalTime anotherTime = LocalTime.of(13, 12, 45);
ZonedDateTime zonedDateTime = ZonedDateTime.of(anotherSummerDay, anotherTime, ZoneId.of("Europe/Helsinki"));
System.out.println(
  DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL)
  .format(zonedDateTime));
System.out.println(
  DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
  .format(zonedDateTime));
System.out.println(
  DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
  .format(zonedDateTime));
System.out.println(
  DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT)
  .format(zonedDateTime));

Обратите внимание, что на этот раз мы использовали методofLocalizedDateTime() дляDateTimeFormatter.

И результат, который мы получаем:

Tuesday, August 23, 2016 1:12:45 PM EEST
August 23, 2016 1:12:45 PM EEST
Aug 23, 2016 1:12:45 PM
8/23/16 1:12 PM

Мы также можем использоватьFormatStyle для анализа даты и времениString, преобразовывая его, например, вZonedDateTime.

Затем мы можем использовать проанализированное значение для манипуляции с датой и временем:

ZonedDateTime dateTime = ZonedDateTime.from(
  DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL)
    .parse("Tuesday, August 23, 2016 1:12:45 PM EET"));
System.out.println(dateTime.plusHours(9));

Вывод этого фрагмента: «2016-08-23T22: 12: 45 + 03: 00 [Европа / Бухарест]», обратите внимание, что время изменилось на «22:12:45».

4. DateTimeFormatter с пользовательскими форматами

Predefined and built-in formatters and styles can cover a lot of situations. Однако иногда нам нужно отформатировать дату и время несколько иначе. Это когда пользовательские шаблоны форматирования вступают в игру.

4.1. DateTimeFormatter для даты

Предположим, мы хотим представить объектjava.time.LocalDate в обычном европейском формате, например 31.12.2018. Для этого мы могли бы вызвать фабричный методDateTimeFormatter.ofPattern(“dd.MM.yyyy”).

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

String europeanDatePattern = "dd.MM.yyyy";
DateTimeFormatter europeanDateFormatter = DateTimeFormatter.ofPattern(europeanDatePattern);
System.out.println(europeanDateFormatter.format(LocalDate.of(2016, 7, 31)));

Вывод этого фрагмента кода будет «31.07.2016».

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

  Symbol  Meaning                     Presentation      Examples
  ------  -------                     ------------      -------
   u       year                        year              2004; 04
   y       year-of-era                 year              2004; 04
   M/L     month-of-year               number/text       7; 07; Jul; July; J
   d       day-of-month                number            10

Это отрывок из классов отofficial Java documentation доDateTimeFormatter.

The number of letters in the pattern format is significant.

Если мы используем двухбуквенный шаблон для месяца, мы получим двухзначное представление месяца. Если номер месяца меньше 10, он будет дополнен нулем. Когда нам не нужно упомянутое заполнение нулями, мы можем использовать однобуквенный образец «M», который покажет январь как «1».

Если нам случится использовать четырехбуквенный шаблон для месяца «ММММ», то мы получим представление в «полной форме». В нашем примере это «июль». Пятибуквенный шаблон «MMMMM» заставит средство форматирования использовать «узкую форму». В нашем случае будет использоваться буква «J».

Аналогично, пользовательский шаблон форматирования также может использоваться для анализа строки, содержащей дату:

DateTimeFormatter europeanDateFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
System.out.println(LocalDate.from(europeanDateFormatter.parse("15.08.2014")).isLeapYear());

Этот фрагмент кода проверяет, является ли дата «15.08.2014» одной из високосных, а это не так.

4.2. DateTimeFormatter для времени

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

  Symbol  Meaning                     Presentation      Examples
  ------  -------                     ------------      -------
   H       hour-of-day (0-23)          number            0
   m       minute-of-hour              number            30
   s       second-of-minute            number            55
   S       fraction-of-second          fraction          978
   n       nano-of-second              number            987654321

ИспользоватьDateTimeFormatter для форматирования экземпляраjava.time.LocalTime довольно просто. Предположим, мы хотим показать время (часы, минуты и секунды), разделенные двоеточием:

String timeColonPattern = "HH:mm:ss";
DateTimeFormatter timeColonFormatter = DateTimeFormatter.ofPattern(timeColonPattern);
LocalTime colonTime = LocalTime.of(17, 35, 50);
System.out.println(timeColonFormatter.format(colonTime));

Это сгенерирует вывод «17:35:50».

Если мы хотим добавить к выводу миллисекунды, мы должны добавить в шаблон «SSS»:

String timeColonPattern = "HH:mm:ss SSS";
DateTimeFormatter timeColonFormatter = DateTimeFormatter.ofPattern(timeColonPattern);
LocalTime colonTime = LocalTime.of(17, 35, 50).plus(329, ChronoUnit.MILLIS);
System.out.println(timeColonFormatter.format(colonTime));

Что дает результат «17:35:50 329».

Обратите внимание, что «ЧЧ» - это график часа дня, который генерирует результат 0–23. Когда мы хотим показать AM / PM, мы должны использовать строчные буквы «чч» для часов и добавить шаблон «а»:

String timeColonPattern = "hh:mm:ss a";
DateTimeFormatter timeColonFormatter = DateTimeFormatter.ofPattern(timeColonPattern);
LocalTime colonTime = LocalTime.of(17, 35, 50);
System.out.println(timeColonFormatter.format(colonTime));

Сгенерированный вывод - «05:35:50 PM».

Мы можем захотеть проанализировать времяString с помощью нашего настраиваемого средства форматирования и проверить, не наступило ли оно до полудня:

DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("hh:mm:ss a");
System.out.println(LocalTime.from(timeFormatter.parse("12:25:30 AM")).isBefore(LocalTime.NOON));

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

4.3. DateTimeFormatter для часовых поясов

Often we want to see a time zone of some specific date-time variable. Если мы используем дату и время на основе Нью-Йорка (UTC -4), мы можем использовать шаблонную букву «z» для имени часового пояса:

String newYorkDateTimePattern = "dd.MM.yyyy HH:mm z";
DateTimeFormatter newYorkDateFormatter = DateTimeFormatter.ofPattern(newYorkDateTimePattern);
LocalDateTime summerDay = LocalDateTime.of(2016, 7, 31, 14, 15);
System.out.println(newYorkDateFormatter.format(ZonedDateTime.of(summerDay, ZoneId.of("UTC-4"))));

Это сгенерирует вывод «31.07.2016 14:15 UTC-04: 00».

Мы можем анализировать строки даты и времени с часовыми поясами, как мы делали ранее:

DateTimeFormatter zonedFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm z");
System.out.println(ZonedDateTime.from(zonedFormatter.parse("31.07.2016 14:15 GMT+02:00")).getOffset().getTotalSeconds());

Результатом этого кода является «7200» секунд или 2 часа, как мы и ожидали.

Мы должны убедиться, что предоставили правильную дату и времяString методуparse(). Если мы передадим «31.07.2016 14:15» без часового пояса вzonedFormatter из последнего фрагмента кода, мы получимDateTimeParseException.

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

In this tutorial, we’ve discussed how to use the DateTimeFormatter class for format dates and times. Мы использовали шаблоны из реальной жизни, которые часто возникают, когда мы работаем с экземплярами даты и времени.

Мы можем узнать больше об API Java 8Date/Time вprevious tutorials. Как всегда, исходный код, используемый в руководстве, доступенover on GitHub.