Рубрики
Без рубрики

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

Узнайте, как использовать класс Java 8 DateTimeFormatter для форматирования и анализа дат и времени

Автор оригинала: baeldung.

1. Обзор

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

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

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

DateTimeFormatter поставляется с несколькими предопределенными форматами даты/времени |, которые соответствуют стандартам 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")));

Большинство предопределенных экземпляров класса DateTimeFormatter ориентированы на стандарт ISO-8601. ISO-8601-это международный стандарт форматирования даты и времени.

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

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

Этот фрагмент генерирует ‘ Пт, 9 марта 2018 00:00:00 -0300 ‘.

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

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

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

3. DateTimeFormatter с FormatStyle

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

В таких случаях мы можем использовать java.time.format.FormatStyle перечисление (ПОЛНОЕ, ДЛИННОЕ, СРЕДНЕЕ, КОРОТКОЕ) значений с помощью нашего 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

Мы также можем использовать предопределенные стили форматирования даты и времени. Чтобы использовать Format Style со временем нам придется использовать 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

Мы также можем использовать Format Style для анализа даты и времени 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 с пользовательскими форматами

Предопределенные и встроенные форматеры и стили могут охватывать множество ситуаций . Однако иногда нам нужно форматировать дату и время несколько иначе. Именно тогда в игру вступают пользовательские шаблоны форматирования.

4.1. DateTimeFormatter для даты

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

Это создаст соответствующий экземпляр 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

Это выдержка из официальной документации Java to DateTimeFormatter класса.

Количество букв в шаблоне формата значимо .

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

Если нам случится использовать четырехбуквенный шаблон для месяца “ММММ”, то мы получим представление “полной формы”. В нашем примере это “Июль”. 5-буквенный шаблон” МММММ” заставит форматер использовать “узкую форму”. В нашем случае будет использоваться “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 “.

Обратите внимание, что “HH”-это часовой паттерн, который генерирует выходные данные 0-23. Когда мы хотим показать AM/PM, мы должны использовать строчные буквы “hh” для часов и добавить шаблон “a”:

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 “.

Возможно, мы захотим разобрать time 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 для часовых поясов

Часто мы хотим видеть часовой пояс какой-то конкретной переменной даты-времени. Если мы случайно используем нью-йоркскую дату-время (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”, без часового пояса, в zoned For matter из последнего фрагмента кода, то получим DateTimeParseException .

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

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

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