Класс Java DateTimeFormatter
DateTimeFormatter — важный класс в API даты и времени (пакет java.time), появившийся в Java 8. Он используется для форматирования и разбора объектов даты и времени. Этот класс предоставляет мощный функционал для работы с отображением и преобразованием значений даты и времени.
Проще говоря, DateTimeFormatter имеет две основные цели:
- Форматирование: преобразует объекты даты и времени (такие как LocalDate, LocalDateTime) в строки в определённом формате
- Парсинг: преобразует строки, соответствующие формату, в объекты даты и времени
Зачем нужен DateTimeFormatter
До Java 8 мы использовали SimpleDateFormat для обработки форматирования и разбора дат, но у него есть несколько недостатков:
- Не потокобезопасен
- Устаревший дизайн
- Неудобная обработка ошибок
DateTimeFormatter решает эти проблемы:
- Потокобезопасность: Экземпляры можно безопасно совместно использовать в многопоточных средах
- Неизменяемый: После создания его нельзя изменить
- Более богатые предопределённые форматы: Предоставляет большое количество встроенных форматов
- Улучшенная обработка ошибок: Предоставляет более подробную информацию об ошибках при сбое разбора
Базовое использование
Предопределённые форматтеры
DateTimeFormatter предоставляет множество предопределённых констант форматтера:
Пример
// Использовать предопределённый форматтер
System.out.println(now.format(DateTimeFormatter.ISO_LOCAL_DATE)); // 2023-11-15
System.out.println(now.format(DateTimeFormatter.ISO_LOCAL_TIME)); // 14:30:45.123
System.out.println(now.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); // 2023-11-15T14:30:45.123
Пользовательские шаблоны
Вы можете создавать пользовательские форматтеры, используя строки шаблонов:
Пример
String formattedDateTime = now.format(formatter); // Форматирование
System.out.println(formattedDateTime); // 2023-11-15 14:30:45
// Разбор
LocalDateTime parsedDateTime = LocalDateTime.parse("2023-11-15 14:30:45", formatter);
// Распространённый китайский формат даты
DateTimeFormatter chineseFormatter = DateTimeFormatter.ofPattern(yyyy-MM-dd);
String formattedDate = today.format(chineseFormatter);
System.out.println(Дата в китайском формате: + formattedDate);
// Разбор строки с китайской датой
String chineseDateStr = 2023-05-20;
LocalDate parsedDate = LocalDate.parse(chineseDateStr, chineseFormatter);
System.out.println(Разобранная дата: + parsedDate);
// Другие распространённые форматы
DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("MM/dd/yyyy");
DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern(yyyy-MM-dd EEEE, Locale.CHINA);
System.out.println(Формат 1: + today.format(formatter1));
System.out.println(Формат 2: + today.format(formatter2));
System.out.println(Формат 3 (с днём недели): + today.format(formatter3));
Локализованные форматы
Вы можете создавать форматтеры на основе разных локалей:
Пример
DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG)
.withLocale(Locale.FRENCH);
String frenchDate = now.format(frenchFormatter);
System.out.println(frenchDate); // 15 novembre 2023
Справочник по буквам шаблона
При создании пользовательских форматов нужно использовать определённые буквы шаблона:
| Буква | Значение | Пример |
|---|---|---|
| y | год | yyyy → 2023 |
| M | month | MM → 11 |
| d | day | dd → 15 |
| H | Час (0-23) | HH → 14 |
| h | Час (1-12) | hh → 02 |
| m | Минута | mm → 30 |
| s | second | ss → 45 |
| S | Миллисекунда | SSS → 123 |
| E | День недели | E → Ср |
| a | AM/PM | a → PM |
Лучшие практики
Повторное использование форматтеров
Поскольку DateTimeFormatter потокобезопасен, рекомендуется определять часто используемые форматтеры как константы:
Пример
public static final DateTimeFormatter STANDARD_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// Использование
String formatted = LocalDateTime.now().format(STANDARD_FORMATTER);
}
Полный пример:
Пример
import java.time.LocalTime;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class ExampleTest {
public static void main(String[] args) {
// 1. LocalDate пример
LocalDate currentDate = LocalDate.now();
System.out.println(Текущая дата: + currentDate);
LocalDate specificDate = LocalDate.of(2023, 5, 20);
System.out.println(Конкретная дата: + specificDate);
// 2. LocalTime пример
LocalTime currentTime = LocalTime.now();
System.out.println(Текущее время: + currentTime);
LocalTime specificTime = LocalTime.of(14, 30, 15);
System.out.println(Конкретное время: + specificTime);
// 3. Пример LocalDateTime
LocalDateTime currentDateTime = LocalDateTime.now();
System.out.println(Текущая дата и время: + currentDateTime);
LocalDateTime specificDateTime = LocalDateTime.of(2023, 5, 20, 14, 30, 15);
System.out.println(Конкретная дата и время: + specificDateTime);
// 4. Пример DateTimeFormatter
// Базовое форматирование
DateTimeFormatter basicFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
System.out.println(Базовое форматирование: + currentDate.format(basicFormatter));
// Китайское форматирование
DateTimeFormatter chineseFormatter = DateTimeFormatter.ofPattern(yyyy-MM-dd, Locale.CHINA);
System.out.println(Китайская дата: + currentDate.format(chineseFormatter));
// Форматирование по-китайски с днём недели
DateTimeFormatter weekFormatter = DateTimeFormatter.ofPattern(yyyy-MM-dd EEEE, Locale.CHINA);
System.out.println(Китайская дата с днём недели: + currentDate.format(weekFormatter));
// Форматирование времени
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(HH:mm:ss);
System.out.println(Китайское время: + currentTime.format(timeFormatter));
// Форматирование даты и времени
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(Стандартная дата и время: + currentDateTime.format(dateTimeFormatter));
// Разбор даты
String dateStr = "2023-05-20";
LocalDate parsedDate = LocalDate.parse(dateStr, basicFormatter);
System.out.println(Разобранная дата: + parsedDate);
// Разбор китайской даты
String chineseDateStr = 2023-05-20;
LocalDate parsedChineseDate = LocalDate.parse(chineseDateStr, chineseFormatter);
System.out.println(Разобранная китайская дата: + parsedChineseDate);
}
}
Вывод:
当前日期: 2025-05-01 特定日期: 2023-05-20 当前时间: 10:46:38.591747 特定时间: 14:30:15 当前日期时间: 2025-05-01T10:46:38.592002 特定日期时间: 2023-05-20T14:30:15 基本格式化: 2025-05-01 中文日期: 2025年05月01日 带星期的中文日期: 2025年05月01日 星期四 中文时间: 10时46分38秒 标准日期时间: 2025-05-01 10:46:38 解析后的日期: 2023-05-20 解析后的中文日期: 2023-05-20
Обработка исключений разбора
Следует обрабатывать возможные исключения при разборе строк:
Пример
LocalDateTime dateTime = LocalDateTime.parse("2023-11-15", formatter);
} catch (DateTimeParseException e) {
System.err.println(Не удалось разобрать дату/время: + e.getMessage());
}
Учитывайте часовые пояса
Если вам нужно обрабатывать часовые пояса, можно использоватьZonedDateTimeи шаблоны с указанием часового пояса:
Пример
ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
System.out.println(zonedDateTime.format(formatter)); // 2023-11-15 14:30:45 CST
Итог
DateTimeFormatter — мощный инструмент для форматирования и разбора в API даты и времени Java 8. По сравнению со старым SimpleDateFormat он безопаснее, гибче и проще в использовании. Освоение DateTimeFormatter позволяет более эффективно обрабатывать различные требования к формату даты и времени.
Запомните ключевые моменты:
- Используйте предопределённые форматтеры для распространённых форматов
- Используйте ofPattern() для создания пользовательских форматов
- Учитывайте требования локализации и часового пояса
- Повторно используйте потокобезопасные экземпляры форматтера
- Правильно обрабатывайте исключения парсинга