LocalDateTime format: примеры (JAVA)

Отображение LocalDateTime в строковый формат
Раздел: Время и дата (Date & Time API)
LocalDateTime format(DateTimeFormatter formatter): String

Общее описание метода format(LocalDateTime)

Метод format у класса java.time.LocalDateTime возвращает строковое представление даты и времени, отформатированное с помощью вышепереданного форматтера. Используется для получения человекочитаемой или машинно-ориентированной строки на основе локального временного значения без зоны и смещения.

Сигнатура метода:

public String format(java.time.format.DateTimeFormatter formatter)

Аргументы:

  • formatter - экземпляр java.time.format.DateTimeFormatter. Обязательный параметр, не должен быть null. Форматтер описывает шаблон, локаль, символы десятичных разделителей и прочие правила форматирования.

Возвращаемое значение:

  • Строка (String) - результат форматирования локальной даты и времени в соответствии с правилами форматтера.

Особенности и замечания:

  • LocalDateTime не содержит информации о временной зоне или смещении. Для вывода с зоной необходимо сначала преобразовать в ZonedDateTime или OffsetDateTime.
  • Шаблоны форматов задаются через DateTimeFormatter.ofPattern и используют символы шаблона (y, M, d, H, m, s, S и т.д.).
  • Локаль и DecimalStyle влияют на названия месяцев, дней недели и символы цифр.
  • При использовании нестандартных требований к форматированию создаются форматтеры через DateTimeFormatterBuilder.

Возможные исключения:

  • NullPointerException - если передать null в качестве форматтера.
  • DateTimeException - при невозможности получить требуемое поле или при ошибках форматтера.

Короткие примеры использования

Создание базового LocalDateTime и простое форматирование разными способами.

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

LocalDateTime dt = LocalDateTime.of(2021, 12, 3, 10, 15, 30, 123_456_789);

// Стандартное ISO
String s1 = dt.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);

// Простая шаблонная строка
DateTimeFormatter f2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
String s2 = dt.format(f2);

// С локалью (название месяца на английском)
DateTimeFormatter f3 = DateTimeFormatter.ofPattern("dd MMM yyyy, HH:mm", Locale.ENGLISH);
String s3 = dt.format(f3);

System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
2021-12-03T10:15:30.123456789
2021-12-03 10:15:30.123
03 Dec 2021, 10:15

Другие варианты: вывод с сокращенным годом, заполнение нулями, использование локализованных стилей.

// Двузначный год
DateTimeFormatter f4 = DateTimeFormatter.ofPattern("yy-MM-dd HH:mm");
System.out.println(dt.format(f4));

// Локализованный стиль
DateTimeFormatter f5 = DateTimeFormatter.ofLocalizedDateTime(java.time.format.FormatStyle.MEDIUM).withLocale(Locale.FRANCE);
System.out.println(dt.format(f5));
21-12-03 10:15
03 déc. 2021 10:15:30

Похожие возможности в Java и их особенности

В экосистеме Java присутствуют альтернативы и смежные подходы к форматированию времени.

  • LocalDateTime.toString() - возвращает строку в формате ISO_LOCAL_DATE_TIME. Быстро и удобно для логов, но ограниченно по настройке.
  • DateTimeFormatter.ofPattern() - создание шаблонных форматтеров для гибкого вывода. Подходит для большинства задач.
  • DateTimeFormatterBuilder - для сложных случаев: условные блоки, опции, пользовательские числовые представления и дробные секунды со сложной логикой.
  • java.text.SimpleDateFormat - устаревший механизм для java.util.Date. Может использоваться в старом коде, но небезопасен для многопоточности и менее предпочтителен по сравнению с java.time.

Рекомендации по выбору:

  • При работе с современным кодом и Java 8+ преимущественно использовать DateTimeFormatter и классы из пакета java.time.
  • Для одного фиксированного ISO-формата можно использовать LocalDateTime.toString() или DateTimeFormatter.ISO_LOCAL_DATE_TIME.
  • Для сложного форматирования с условностями применять DateTimeFormatterBuilder.

Альтернативы в других языках и отличия

Ниже примеры форматирования аналогичного локального времени 2021-12-03 10:15:30 + дробные секунды в разных языках. Отличия в синтаксисе шаблонов и точности дробной части.

PHP

$dt = DateTime::createFromFormat('Y-m-d H:i:s.u', '2021-12-03 10:15:30.123456');
echo $dt->format('Y-m-d H:i:s.u');
2021-12-03 10:15:30.123456

JavaScript (Node.js, браузер)

const dt = new Date(2021, 11, 3, 10, 15, 30, 123); // месяц 11 = декабрь
console.log(dt.toISOString());
// или локальный вывод
console.log(dt.toLocaleString('en-GB'));
2021-12-03T07:15:30.123Z
03/12/2021, 10:15:30

Python

from datetime import datetime
dt = datetime(2021, 12, 3, 10, 15, 30, 123456)
print(dt.strftime('%Y-%m-%d %H:%M:%S.%f'))
2021-12-03 10:15:30.123456

PostgreSQL (SQL)

SELECT to_char(timestamp '2021-12-03 10:15:30.123456', 'YYYY-MM-DD HH24:MI:SS.US');
2021-12-03 10:15:30.123456

C# (.NET)

using System;
DateTime dt = new DateTime(2021, 12, 3, 10, 15, 30, 123);
Console.WriteLine(dt.ToString("yyyy-MM-dd HH:mm:ss.fff"));
2021-12-03 10:15:30.123

Go (golang)

package main
import (
    "fmt"
    "time"
)
func main(){
    dt := time.Date(2021, time.December, 3, 10, 15, 30, 123456789, time.Local)
    fmt.Println(dt.Format("2006-01-02 15:04:05.000000000"))
}
2021-12-03 10:15:30.123456789

Lua

-- Lua работает с меткой времени в секундах
local ts = os.time{year=2021, month=12, day=3, hour=10, min=15, sec=30}
print(os.date("%Y-%m-%d %H:%M:%S", ts))
2021-12-03 10:15:30

Отличия от Java:

  • Серии шаблонов у разных языков различаются: Java использует свои символы, Go применяет эталонную дату 2006-01-02 15:04:05.
  • Точность дробной секунды варьируется. Java поддерживает наносекунды, Python и PostgreSQL обычно микросекунды, C# часто миллисекунды по умолчанию.
  • Преобразование между локальным временем и UTC/часовыми поясами в некоторых языках требует явного указания зоны.

Типичные ошибки при использовании format

Рассмотрены распространенные ошибки с примерами и результатами.

1) Null в качестве форматтера

import java.time.LocalDateTime;
LocalDateTime dt = LocalDateTime.now();
String s = dt.format(null);
Exception in thread "main" java.lang.NullPointerException
    at java.base/java.time.temporal.TemporalAccessor.query(TemporalAccessor.java:...)
    at java.base/java.time.format.DateTimeFormatter.formatTo(DateTimeFormatter.java:...)
    ...

2) Неправильный шаблон при создании DateTimeFormatter.ofPattern

import java.time.format.DateTimeFormatter;
DateTimeFormatter f = DateTimeFormatter.ofPattern("YYYYY-MM-dd");
Exception in thread "main" java.lang.IllegalArgumentException: Invalid pattern letter: Y
    at java.base/java.time.format.DateTimeFormatterBuilder.parsePattern(DateTimeFormatterBuilder.java:...)
    ...

3) Форматирование поля, отсутствующего в TemporalAccessor - обычно возникает при комбинировании неподходящего форматтера и другого типа временного объекта

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
LocalDate d = LocalDate.of(2021, 12, 3);
DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String s = d.format(f);
Exception in thread "main" java.time.DateTimeException: Unable to extract value: class java.time.temporal.ChronoField
    at java.base/java.time.LocalDate.getLong(LocalDate.java:...)
    at java.base/java.time.format.DateTimePrintContext.getValue(DateTimePrintContext.java:...)
    ...

4) Ошибки локали и кодировки при выводе названий месяцев - при неверной локали могут отображаться непривычные названия; стоит явно указывать Locale при необходимости.

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

Изменения и эволюция API

Краткая история и заметные изменения, влияющие на форматирование LocalDateTime.

  • Java 8 - введение пакета java.time, включая LocalDateTime и DateTimeFormatter. Это основная современная замена java.util.Date и SimpleDateFormat.
  • Последующие версии Java фокусировались на улучшении производительности и корректности локализации. API DateTimeFormatter и DateTimeFormatterBuilder оставались стабильными, расширялись возможности для гибкой сборки форматтеров.
  • Добавления обычно касались новых локалей, улучшений в алгоритмах парсинга и форматирования, а также исправлений ошибок. Рекомендуется проверять заметки релиза конкретной версии JDK при миграции.

Расширенные примеры и редкие сценарии

Подробные примеры: условные части формата, дробные секунды разной длины, преобразование в ZonedDateTime, пользовательские DecimalStyle и appendValueReduced.

1) Форматтер с опциональной частью (через DateTimeFormatterBuilder)

Пример java
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;

LocalDateTime dt = LocalDateTime.of(2021, 12, 3, 10, 15, 30);

DateTimeFormatter f = new DateTimeFormatterBuilder()
    .appendPattern("yyyy-MM-dd HH:mm")
    .optionalStart()
      .appendPattern(":ss")
    .optionalEnd()
    .toFormatter();

System.out.println(dt.format(f));

// Если есть наносекунды
LocalDateTime dt2 = LocalDateTime.of(2021,12,3,10,15,30,123_000_000);
System.out.println(dt2.format(f));
2021-12-03 10:15:30
2021-12-03 10:15:30

2) Контроль дробных секунд с произвольной шириной

Пример java
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoField;

LocalDateTime dt = LocalDateTime.of(2021,12,3,10,15,30,123_456_789);

DateTimeFormatter f = new DateTimeFormatterBuilder()
    .appendPattern("yyyy-MM-dd HH:mm:ss")
    .appendFraction(ChronoField.NANO_OF_SECOND, 1, 9, true) // от 1 до 9 цифр
    .toFormatter();

System.out.println(dt.format(f));
2021-12-03 10:15:30.123456789

3) Форматирование с пользовательским DecimalStyle (например, заменой цифр)

Пример java
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DecimalStyle;
import java.util.Locale;

LocalDateTime dt = LocalDateTime.of(2021,12,3,10,15,30);
DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
DecimalStyle arabicIndic = DecimalStyle.of(Locale.forLanguageTag("ar")).withZeroDigit('\u0660');
System.out.println(f.withDecimalStyle(arabicIndic).format(dt));
٢٠٢١-١٢-٠٣ ١٠:١٥:٣٠

4) Форматирование LocalDateTime с зоной через преобразование

Пример java
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

LocalDateTime dt = LocalDateTime.of(2021,12,3,10,15,30);
ZonedDateTime z = dt.atZone(ZoneId.of("Europe/Moscow"));
System.out.println(z.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss Z")));

// Для вывода имени зоны
System.out.println(z.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z")));
2021-12-03 10:15:30 +0300
2021-12-03 10:15:30 MSK

5) Снижение разрядности года при помощи appendValueReduced

Пример java
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoField;

LocalDateTime dt = LocalDateTime.of(1999,12,31,23,59,59);
DateTimeFormatter f = new DateTimeFormatterBuilder()
    .appendValueReduced(ChronoField.YEAR, 2, 2, 2000)
    .appendLiteral('-')
    .appendPattern("MM-dd HH:mm:ss")
    .toFormatter();

System.out.println(dt.format(f));
99-12-31 23:59:59

6) Пользовательский TemporalQuery для форматирования в специфичный выходной тип - пример сложных преобразований выполняется аналогично через builder и query; чаще применяется для парсинга, но и для специальных задач форматирования возможны расширения.

Пояснения: примеры демонстрируют создание гибких форматтеров, управление точностью дробной части, работу с локалями и замену цифр. Для задач с зонами рекомендуется сначала преобразовать LocalDateTime в ZonedDateTime.

джава LocalDateTime format function comments

En
LocalDateTime format Formats this date-time using the specified formatter