Ръководство за DateTimeFormatter

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);

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

3. DateTimeFormatter с FormatStyle

Понякога може да искаме да отпечатаме дати по разбираем от човека начин.

В такива случаи можем да използваме стойности на java.time.format.FormatStyle enum (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));

Забележете, че този път използвахме методаLocalizedDateTime () на 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, за да анализираме низ от време и дата, като го преобразуваме например в 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 („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

Това е извлечение от официалната документация на Java към класа DateTimeFormatter .

Броят на буквите във формата на шаблона е значителен .

Ако използваме двубуквен шаблон за месеца, ще получим двуцифрено месечно представяне. Ако номерът на месеца е по-малък от 10, той ще бъде подплатен с нула. Когато не се нуждаем от споменатата подложка с нули, можем да използваме еднобуквен шаблон „M“, който ще покаже януари като „1“.

Ако случайно използваме модел от четири букви за месеца „MMMM“, тогава ще получим представяне в „пълна форма“. В нашия пример това е „юли“. Модел с 5 букви „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 “.

Обърнете внимание, че „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 “.

We may want to parse time String with our custom formatter and check if it is before noon:

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

The output of this last snippet shows that the given time is actually before noon.

4.3. DateTimeFormatter for Time Zones

Often we want to see a time zone of some specific date-time variable. If we happen to use New York-based date-time (UTC -4), we may use “z” pattern-letter for time-zone name:

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"))));

This will generate the output “31.07.2016 14:15 UTC-04:00”.

We can parse date time strings with time zones just like we did earlier:

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());

The output of this code is “7200” seconds, or 2 hours, as we'd expect.

Трябва да се уверим, че предоставяме правилен низ за час и дата за метода parse () . Ако преминем “31.07.2016 14:15”, без часова зона до zonedFormatter от последния кодов фрагмент, ще получим DateTimeParseException .

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

В този урок обсъдихме как да използваме класа DateTimeFormatter за форматиране на дати и часове. Използвали сме примерни модели от реалния живот, които често възникват, когато работим с инстанции за дата и час.

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