Как анализировать / форматировать даты с LocalDateTime? (Java 8)

В Java 8 добавлен новый API java.time для работы с датами и временем ( JSR 310).

У меня есть дата и время в виде строки (например, "2014-04-08 12:30"). Как я могу получить LocalDateTime экземпляр из заданной строки?

После того, как я закончил работать с LocalDateTime Объект: Как я могу затем преобразовать LocalDateTime экземпляр обратно в строку в том же формате, как показано выше?

12 ответов

Решение

Разбор даты и времени

Чтобы создать LocalDateTime объект из строки вы можете использовать статический LocalDateTime.parse() метод. Требуется строка и DateTimeFormatter в качестве параметра. DateTimeFormatter используется для указания даты / времени.

String str = "1986-04-08 12:30";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
LocalDateTime dateTime = LocalDateTime.parse(str, formatter);

Форматирование даты и времени

Чтобы создать отформатированную строку из LocalDateTime объект, который вы можете использовать format() метод.

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
LocalDateTime dateTime = LocalDateTime.of(1986, Month.APRIL, 8, 12, 30);
String formattedDateTime = dateTime.format(formatter); // "1986-04-08 12:30"

Обратите внимание, что есть некоторые часто используемые форматы даты / времени, предопределенные как константы в DateTimeFormatter, Например: использование DateTimeFormatter.ISO_DATE_TIME отформатировать LocalDateTime Экземпляр сверху приведет к строке "1986-04-08T12:30:00",

parse() а также format() методы доступны для всех объектов, связанных с датой и временем (например, LocalDate или же ZonedDateTime)

Вы также можете использовать LocalDate.parse() или же LocalDateTime.parse() на String без указания шаблона, если String в формате ISO-8601.

например,

String strDate = "2015-08-04";
LocalDate aLD = LocalDate.parse(strDate);
System.out.println("Date: " + aLD);

String strDatewithTime = "2015-08-04T10:11:30";
LocalDateTime aLDT = LocalDateTime.parse(strDatewithTime);
System.out.println("Date with Time: " + aLDT);

Выход,

Date: 2015-08-04
Date with Time: 2015-08-04T10:11:30

и использовать DateTimeFormatter только если вам приходится иметь дело с другими шаблонами дат, например, dd MMM uuuu представляет день месяца (две цифры), три буквы названия месяца (январь, февраль, мар,...) и четырехзначный год:

DateTimeFormatter dTF = DateTimeFormatter.ofPattern("dd MMM uuuu");
String anotherDate = "04 Aug 2015";
LocalDate lds = LocalDate.parse(anotherDate, dTF);
System.out.println(anotherDate + " parses to " + lds);

Выход

04 Aug 2015 parses to 2015-08-04

также помните, что DateTimeFormatter объект является двунаправленным; он может анализировать как ввод, так и формат вывода.

String strDate = "2015-08-04";
LocalDate aLD = LocalDate.parse(strDate);
DateTimeFormatter dTF = DateTimeFormatter.ofPattern("dd MMM uuuu");
System.out.println(aLD + " formats as " + dTF.format(aLD));

Выход

2015-08-04 formats as 04 Aug 2015

(см. полный список шаблонов для форматирования и анализа DateFormatter)

  Symbol  Meaning                     Presentation      Examples
  ------  -------                     ------------      -------
   G       era                         text              AD; Anno Domini; A
   u       year                        year              2004; 04
   y       year-of-era                 year              2004; 04
   D       day-of-year                 number            189
   M/L     month-of-year               number/text       7; 07; Jul; July; J
   d       day-of-month                number            10

   Q/q     quarter-of-year             number/text       3; 03; Q3; 3rd quarter
   Y       week-based-year             year              1996; 96
   w       week-of-week-based-year     number            27
   W       week-of-month               number            4
   E       day-of-week                 text              Tue; Tuesday; T
   e/c     localized day-of-week       number/text       2; 02; Tue; Tuesday; T
   F       week-of-month               number            3

   a       am-pm-of-day                text              PM
   h       clock-hour-of-am-pm (1-12)  number            12
   K       hour-of-am-pm (0-11)        number            0
   k       clock-hour-of-am-pm (1-24)  number            0

   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
   A       milli-of-day                number            1234
   n       nano-of-second              number            987654321
   N       nano-of-day                 number            1234000000

   V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
   z       time-zone name              zone-name         Pacific Standard Time; PST
   O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00;
   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15;
   x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15;
   Z       zone-offset                 offset-Z          +0000; -0800; -08:00;

   p       pad next                    pad modifier      1

   '       escape for text             delimiter
   ''      single quote                literal           '
   [       optional section start
   ]       optional section end
   #       reserved for future use
   {       reserved for future use
   }       reserved for future use

Оба ответа выше очень хорошо объясняют вопрос о строковых шаблонах. Тем не менее, на случай, если вы работаете с ISO 8601, нет необходимости применять DateTimeFormatter так как LocalDateTime уже подготовлен для этого:

Преобразовать LocalDateTime в строку часового пояса ISO8601

LocalDateTime ldt = LocalDateTime.now(); 
ZonedDateTime zdt = ldt.atZone(ZoneOffset.UTC); //you might use a different zone
String iso8601 = zdt.toString();

Преобразовать из строки ISO8601 обратно в LocalDateTime

String iso8601 = "2016-02-14T18:32:04.150Z";
ZonedDateTime zdt = ZonedDateTime.parse(iso8601);
LocalDateTime ldt = zdt.toLocalDateTime();

Анализ строки с датой и временем на определенный момент времени (Java называет это " Instant") довольно сложно. Java решает эту проблему в нескольких итерациях. Последняя версия, java.time а также java.time.chrono, покрывает почти все потребности (кроме Time Dilation:)).

Однако такая сложность вносит много путаницы.

Ключ к пониманию синтаксического анализа даты:

Почему в Java так много способов разобрать дату

  1. Есть несколько систем измерения времени. Например, исторические японские календари были выведены из временных диапазонов правления соответствующего императора или династии. Тогда есть, например, временная метка UNIX. К счастью, весь мир (деловой) смог использовать то же самое.
  2. Исторически сложилось так, что системы переключались с / на по разным причинам. Например, от юлианского календаря к григорианскому календарю в 1582 году. Итак, к "западным" датам, предшествующим этому, нужно относиться иначе.
  3. И, конечно, изменение произошло не сразу. Поскольку календарь исходил из штаб-квартир одной религии, а другие части Европы верили в другие диеты, например, Германия не перешла на него до 1700 года.

... и почему LocalDateTime, ZonedDateTimeи другие. так сложно

  1. Есть часовые пояса. Часовой пояс - это, по сути, "полоса" *[1] на поверхности Земли, власти которой следуют тем же правилам, когда у нее есть какое временное смещение. Сюда входят правила летнего времени.
    Часовые пояса меняются со временем для разных областей, в основном в зависимости от того, кто кого побеждает. И правила одного часового пояса тоже меняются.

  2. Есть временные сдвиги. Это не то же самое, что и часовые пояса, потому что часовой пояс может быть, например, "Прага", но со смещением летнего и зимнего времени.
    Если вы получаете метку времени с часовым поясом, смещение может варьироваться в зависимости от того, в какой части года оно находится. Во время високосного часа метка времени может означать 2 разных раза, поэтому без дополнительной информации ее нельзя будет надежно определить. преобразован.
    Примечание. Под меткой времени я подразумеваю "строку, содержащую дату и / или время, необязательно с часовым поясом и / или смещением времени".

  3. Несколько часовых поясов могут иметь одно и то же смещение времени для определенных периодов. Например, часовой пояс GMT/UTC совпадает с часовым поясом "Лондон", когда смещение летнего времени не действует.

Чтобы сделать это немного сложнее (но это не слишком важно для вашего варианта использования):

  1. Ученые наблюдают за динамикой Земли, которая меняется со временем; исходя из этого, они добавляют секунды в конце отдельных лет. (Так2040-12-31 24:00:00может быть допустимой датой и временем.) Это требует регулярного обновления метаданных, которые системы используют для правильного преобразования даты. Например, в Linux вы получаете регулярные обновления пакетов Java, включая эти новые данные.
  2. Обновления не всегда сохраняют предыдущее поведение как для исторических, так и для будущих отметок времени. Таким образом, может случиться так, что анализ двух временных меток при изменении некоторого часового пояса при их сравнении может дать разные результаты при работе в разных версиях программного обеспечения. Это также относится к сравнению часового пояса, на который влияют, и другого часового пояса.

    Если это вызывает ошибку в вашем программном обеспечении, подумайте об использовании какой-нибудь временной метки, не имеющей таких сложных правил, как временная метка UNIX.

  3. Из-за 7 для будущих дат мы не можем точно конвертировать даты. Так, например, текущий разбор8524-02-17 12:00:00 может отключиться через пару секунд от будущего разбора.

API-интерфейсы JDK для этого развивались с учетом современных потребностей.

  • В ранних выпусках Java только java.util.Dateу которого был немного наивный подход, предполагавший, что есть только год, месяц, день и время. Этого быстро оказалось недостаточно.
  • Кроме того, потребности баз данных были разными, поэтому довольно рано, java.sql.Date был введен со своими ограничениями.
  • Поскольку ни один из них не охватывал разные календари и часовые пояса, Calendar Был представлен API.
  • Это все еще не покрывает сложность часовых поясов. И тем не менее, сочетание вышеуказанных API было действительно сложной задачей. Когда разработчики Java начали работать над глобальными веб-приложениями, библиотеки, предназначенные для большинства случаев использования, такие как JodaTime, быстро стали популярными. JodaTime был стандартом де-факто около десяти лет.
  • Но JDK не интегрировался с JodaTime, поэтому работать с ним было немного громоздко. Итак, после очень долгого обсуждения того, как подойти к этому вопросу, JSR-310 был создан в основном на основе JodaTime.

Как с этим бороться в Java java.time

Определите, какой тип анализировать метку времени

Когда вы используете строку с меткой времени, вам нужно знать, какую информацию она содержит. Это ключевой момент. Если вы не поняли это правильно, вы получите загадочные исключения, такие как "Невозможно создать мгновенный" или "Отсутствует смещение зоны" или "Неизвестный идентификатор зоны" и т. Д.

В нем есть дата и время?

  1. Есть ли смещение по времени?
    Смещение по времени - это+hh:mmчасть. Иногда,+00:00 может быть заменен на Z как "зулусское время", UTC как всемирное координированное время, или GMTкак среднее время по Гринвичу. Они также устанавливают часовой пояс.
    Для этих отметок времени вы используете OffsetDateTime.

  2. Есть ли часовой пояс?
    Для этих отметок времени вы используете ZonedDateTime.
    Зона указывается либо

    • название ("Прага", "Тихоокеанское стандартное время", "PST") или
    • "идентификатор зоны" ("Америка / Лос-Анджелес", "Европа / Лондон"), представленный java.time.ZoneId.

    Список часовых поясов составляется "базой данных TZ" при поддержке ICAAN.

    Согласно с ZoneId's javadoc, идентификатор зоны также может быть определен как Zи смещение. Я не уверен, как это соотносится с реальными зонами. Если метка времени, которая имеет только TZ, попадает в високосный час изменения смещения времени, то это неоднозначно, и интерпретация подлежитResolverStyle, Смотри ниже.

  3. Если ни того, ни другого, то отсутствующий контекст предполагается или игнорируется. И решать должен потребитель. Поэтому его нужно проанализировать какLocalDateTime и преобразован в OffsetDateTime добавив недостающую информацию:

    • Вы можете предположить, что это время UTC. Добавьте смещение UTC на 0 часов.
    • Вы можете предположить, что это время того места, где происходит конверсия. Преобразуйте его, добавив часовой пояс системы.
    • Можно пренебречь и просто использовать как есть. Это полезно, например, для двухкратного сравнения или вычитания (см. Duration), или когда вы не знаете, и это не имеет особого значения (например, расписание местных автобусов).

Информация о неполном времени

  • В зависимости от того, что содержит метка времени, вы можете взять LocalDate, LocalTime, OffsetTime, MonthDay, Year, или YearMonth из этого.

Если у вас есть полная информация, вы можете получить java.time.Instant. Это также внутренне используется для преобразования междуOffsetDateTime а также ZonedDateTime.

Выясните, как это разобрать

Существует обширная документация по DateTimeFormatter который может как анализировать строку отметки времени, так и преобразовывать ее в строку.

Предварительно созданоDateTimeFormatters должен охватывать все стандартные форматы меток времени. Например,ISO_INSTANT может разбирать 2011-12-03T10:15:30.123457Z.

Если у вас есть специальный формат, вы можете создать свой собственный DateTimeFormatter (который также является парсером).

private static final DateTimeFormatter TIMESTAMP_PARSER = new DateTimeFormatterBuilder()
   .parseCaseInsensitive()
   .append(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SX"))
   .toFormatter();

Рекомендую посмотреть исходный код DateTimeFormatter и вдохновитесь тем, как создать его, используя DateTimeFormatterBuilder. Пока вы там, также посмотритеResolverStyle который определяет, является ли анализатор LENIENT, SMART или STRICT для форматов и неоднозначной информации.

TemporalAccessor

Частая ошибка заключается в том, чтобы вдаваться в сложность TemporalAccessor. Это связано с тем, как разработчики привыкли работать сSimpleDateFormatter.parse(String). Правильно,DateTimeFormatter.parse("...") дает тебе TemporalAccessor.

// No need for this!
TemporalAccessor ta = TIMESTAMP_PARSER.parse("2011-... etc");

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

OffsetDateTime myTimestamp = OffsetDateTime.parse("2011-12-03T10:15:30.123457Z", TIMESTAMP_PARSER);

На самом деле вам не нужно DateTimeFormatterили. Типы, которые вы хотите проанализировать, имеютparse(String) методы.

OffsetDateTime myTimestamp = OffsetDateTime.parse("2011-12-03T10:15:30.123457Z");

Что касается TemporalAccessor, вы можете использовать его, если имеете смутное представление о том, какая информация содержится в строке, и хотите принять решение во время выполнения.

Надеюсь, я пролил свет на вашу душу:)

Примечание: есть задний порт java.timeна Java 6 и 7: ThreeTen-Backport. Для Android есть ThreeTenABP.

[1] Не только то, что это не полосы, но и некоторые странные крайности. Например, некоторые соседние тихоокеанские острова имеют часовые пояса +14:00 и -11:00. Это означает, что хотя на одном острове 1 мая в 15:00, на другом не так далеко, это все еще 30 апреля в 12:00 (если я правильно посчитал:))

Еще одна вещь, которую следует отметить LocalDateTime.parse заключается в том, что вы не можете использовать его с настраиваемым средством форматирования только с символами средства форматирования даты, такими как uuuuMMdd. В этом случае вам следует использовать LocalDate.parseвместо. Например:

      String s = "20210223";
        
// ok
LocalDate.parse(s, DateTimeFormatter.ofPattern("uuuuMMdd"));
        
// java.time.format.DateTimeParseException
LocalDateTime.parse(s, DateTimeFormatter.ofPattern("uuuuMMdd")); 

ПОЛУЧИТЬ ТЕКУЩЕЕ ВРЕМЯ UTC В ТРЕБУЕМОМ ФОРМАТЕ

// Current UTC time
        OffsetDateTime utc = OffsetDateTime.now(ZoneOffset.UTC);

        // GET LocalDateTime 
        LocalDateTime localDateTime = utc.toLocalDateTime();
        System.out.println("*************" + localDateTime);

        // formated UTC time
        DateTimeFormatter dTF = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
        System.out.println(" formats as " + dTF.format(localDateTime));

        //GET UTC time for current date
        Date now= new Date();
        LocalDateTime utcDateTimeForCurrentDateTime = Instant.ofEpochMilli(now.getTime()).atZone(ZoneId.of("UTC")).toLocalDateTime();
        DateTimeFormatter dTF2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
        System.out.println(" formats as " + dTF2.format(utcDateTimeForCurrentDateTime));

Все ответы хороши. В java8 + есть следующие шаблоны для синтаксического анализа и форматирования часового пояса: V, z, O, X, x, Z.

Вот они, на разбор , по правилам из документации:

         Symbol  Meaning                     Presentation      Examples
   ------  -------                     ------------      -------
   V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
   z       time-zone name              zone-name         Pacific Standard Time; PST
   O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00;
   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15;
   x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15;
   Z       zone-offset                 offset-Z          +0000; -0800; -08:00;

А как насчет форматирования ? Вот образец даты (при условии, что ZonedDateTime), которые показывают поведение этих шаблонов для разных шаблонов форматирования:

      // The helper function:
static void printInPattern(ZonedDateTime dt, String pattern) {
    System.out.println(pattern + ": " + dt.format(DateTimeFormatter.ofPattern(pattern)));
}        

// The date:
String strDate = "2020-11-03 16:40:44 America/Los_Angeles";
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss zzzz");
ZonedDateTime dt = ZonedDateTime.parse(strDate, format);
// 2020-11-03T16:40:44-08:00[America/Los_Angeles]

// Rules:
// printInPattern(dt, "V");     // exception!
printInPattern(dt, "VV");       // America/Los_Angeles
// printInPattern(dt, "VVV");   // exception!
// printInPattern(dt, "VVVV");  // exception!
printInPattern(dt, "z");        // PST
printInPattern(dt, "zz");       // PST
printInPattern(dt, "zzz");      // PST
printInPattern(dt, "zzzz");     // Pacific Standard Time
printInPattern(dt, "O");        // GMT-8
// printInPattern(dt, "OO");    // exception!
// printInPattern(dt, "OO0");   // exception!
printInPattern(dt, "OOOO");     // GMT-08:00
printInPattern(dt, "X");        // -08
printInPattern(dt, "XX");       // -0800
printInPattern(dt, "XXX");      // -08:00
printInPattern(dt, "XXXX");     // -0800
printInPattern(dt, "XXXXX");    // -08:00
printInPattern(dt, "x");        // -08
printInPattern(dt, "xx");       // -0800
printInPattern(dt, "xxx");      // -08:00
printInPattern(dt, "xxxx");     // -0800
printInPattern(dt, "xxxxx");    // -08:00
printInPattern(dt, "Z");        // -0800
printInPattern(dt, "ZZ");       // -0800
printInPattern(dt, "ZZZ");      // -0800
printInPattern(dt, "ZZZZ");     // GMT-08:00
printInPattern(dt, "ZZZZZ");    // -08:00

В случае положительного смещения + знаковый знак используется везде (где есть - сейчас) и никогда не опускается.

Это хорошо работает для новых java.timeтипы. Если вы собираетесь использовать их для java.util.Date или же java.util.Calendar - не все будут работать, поскольку эти типы не работают (и поэтому помечены как устаревшие, пожалуйста, не используйте их)

Универсальный метод выглядит следующим образом. Это работает для:

  • гггг-ММ-дд ЧЧ:мм:сс.ССС

  • гггг-ММ-дд ЧЧ:мм:сс.С

  • гггг-ММ-дд ЧЧ:мм:сс

  • гггг-ММ-дд ЧЧ:мм

  • гггг-ММ-дд ЧЧ

  • гггг-мм-дд

            public static final String DATE_FORMAT_YYYY_MM_DD_HH_MM_SS_SSS = "yyyy-MM-dd HH:mm:ss.SSS";
    
    public LocalDateTime stringToLocalDateTime(String s){
        return LocalDateTime.parse(s, DateTimeFormatter.ofPattern(DATE_FORMAT_YYYY_MM_DD_HH_MM_SS_SSS.substring(0, s.length())));
    }
    

Возьмем два вопроса, пример строки "2014-04-08 12:30"

Как я могу получить экземпляр LocalDateTime из заданной строки?

import java.time.format.DateTimeFormatter
import java.time.LocalDateTime

final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")

// Parsing or conversion
final LocalDateTime dt = LocalDateTime.parse("2014-04-08 12:30", formatter)

dt должен позволить вам все операции, связанные с датой и временем

Как я могу затем преобразовать экземпляр LocalDateTime обратно в строку с тем же форматом?

final String date = dt.format(formatter)

Мне показалось прекрасным охватить несколько вариантов формата даты и времени следующим образом:

final DateTimeFormatterBuilder dtfb = new DateTimeFormatterBuilder();
dtfb.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSS"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSS"))
    .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"))
    .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SS"))
    .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S"))
    .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
    .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
    .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0);

Когда у меня есть переменная типаjava.time.LocalDateTimeчтобы получить дату в желаемом формате, и я не хочу использовать промежуточные классы, я просто делаю:

      LocalDateTime nowDate = LocalDateTime.now();
String nowDateInString = nowDate.toString().substring(0,16).replace("T", " ");


Значение nowDateInString: 2023-10-27 11:17

Вы можете настроить значение «подстроки», чтобы получить то, что вы хотите.

Хочу отметить, что этот метод подходит не во всех ситуациях.

На этот вопрос уже есть много хороших ответов. Этот ответ показывает, как использовать предопределенные s для создания, которые могут анализировать заданную строку даты и времени.

Однако форматирование полученногоLocalDateTimeиспользуя этоDateTimeFormatterвернет строку со временем вHH:mm:ssформат. Чтобы ограничить строку времени доHH:mmформат, нам все еще нужно использовать шаблонuuuu-MM-dd HH:mmкак и другие ответы.

Демо :

      class Main {
    public static void main(String[] args) {
        DateTimeFormatter dtf = new DateTimeFormatterBuilder()
                .append(DateTimeFormatter.ISO_LOCAL_DATE)
                .appendLiteral(' ')
                .append(DateTimeFormatter.ISO_LOCAL_TIME)
                .toFormatter(Locale.ENGLISH);

        String strDateTime = "2014-04-08 12:30";
        LocalDateTime ldt = LocalDateTime.parse(strDateTime, dtf);
        System.out.println(ldt);

        // However, formatting the obtained LocalDateTime using this DateTimeFormatter
        // will return a string with time in HH:mm:ss format. To restrict the time
        // string to HH:mm format, we still have to use the pattern, uuuu-MM-dd HH:mm as
        // other answers have done.
        String strDateTimeFormatted = ldt.format(dtf);
        System.out.println(strDateTimeFormatted);

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm", Locale.ENGLISH);
        strDateTimeFormatted = ldt.format(formatter);
        System.out.println(strDateTimeFormatted);
    }
}

Выход :

      2014-04-08T12:30
2014-04-08 12:30:00
2014-04-08 12:30

ONLINE DEMO

Примечание . Здесь вы можете использовать вместо, но я предпочитаю uкy.

Узнайте больше о современном API Date-Time от Trail: Date Time.

Другие вопросы по тегам