1. DateTimeFormatter: что это и зачем нужен
В реальных программах даты редко живут только внутри кода. Обычно их нужно:
- Преобразовывать в строку для вывода в консоль, на экран или в файл (например, "01.06.2025 14:30").
- Парсить строку, то есть превращать строку, введённую пользователем или пришедшую из файла, обратно в объект даты/времени.
Для этого в Java есть мощный и удобный инструмент — класс java.time.format.DateTimeFormatter.
Можно сказать, что DateTimeFormatter — это переводчик между объектами времени (LocalDate, LocalDateTime, ZonedDateTime, Instant и др.) и строками. Он умеет:
- Превращать объекты дат/времени в строки в нужном формате (format — форматирование).
- Превращать строки в объекты дат/времени (parse — парсинг).
2. Стандартные форматтеры: быстро и просто
Java заботливо подготовила для нас набор стандартных форматтеров, которые покрывают самые популярные форматы ISO (международные стандарты для дат и времени).
Вот некоторые из них:
| Форматтер | Пример строки | Описание |
|---|---|---|
|
2025-06-01 | Только дата (год-месяц-день) |
|
14:30:00 | Только время (часы:минуты:сек) |
|
2025-06-01T14:30:00 | Дата и время без таймзоны |
|
2025-06-01T14:30:00+03:00[Europe/Minsk] | Дата, время и таймзона |
Пример использования стандартного форматтера
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class FormatterDemo {
public static void main(String[] args) {
LocalDate date = LocalDate.now();
// Форматируем дату в строку
String text = date.format(DateTimeFormatter.ISO_LOCAL_DATE);
System.out.println(text); // Например, 2025-06-01
// Парсим строку обратно в дату
LocalDate parsed = LocalDate.parse("2025-06-01", DateTimeFormatter.ISO_LOCAL_DATE);
System.out.println(parsed); // 2025-06-01
}
}
Аналогия
Если бы Java была кофейней, стандартные форматтеры — это "американо", "латте" и "эспрессо". Быстро, стандартно, но иногда хочется чего-то особенного!
3. Пользовательские шаблоны: DateTimeFormatter.ofPattern
Иногда стандартных форматов недостаточно. Например, нужно вывести дату в виде "01.06.2025 14:30", а не "2025-06-01T14:30:00". Для этого мы можем создать свой шаблон с помощью метода DateTimeFormatter.ofPattern(String pattern).
Синтаксис шаблонов
В шаблоне используются специальные буквы:
- y — год (yyyy — 2025)
- M — месяц (MM — 06)
- d — день (dd — 01)
- H — час (24-часовой формат, HH — 14)
- m — минуты (mm — 30)
- s — секунды (ss — 00)
Примеры шаблонов
| Шаблон | Пример результата |
|---|---|
|
01.06.2025 |
|
2025/06/01 |
|
01.06.2025 14:30 |
|
2025-06-01 14:30:00 |
|
1 июня 2025 (при русской локали) |
Пример: форматирование даты и времени
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class CustomFormatDemo {
public static void main(String[] args) {
LocalDateTime dt = LocalDateTime.of(2025, 6, 1, 14, 30);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");
String text = dt.format(formatter);
System.out.println(text); // 01.06.2025 14:30
}
}
Пример: парсинг строки в дату
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class ParseDemo {
public static void main(String[] args) {
String input = "01.06.2025 14:30";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");
LocalDateTime dt = LocalDateTime.parse(input, formatter);
System.out.println(dt); // 2025-06-01T14:30
}
}
Внимание: шаблон должен точно соответствовать строке! Если в строке есть секунды — добавьте :ss в шаблон.
4. Форматирование: превращаем дату/время в строку
Общая схема
- Создаём нужный объект (LocalDate, LocalDateTime, ZonedDateTime и т.д.).
- Создаём или выбираем нужный форматтер.
- Вызываем у объекта метод format(DateTimeFormatter), получаем строку.
Пример: выводим дату в разных форматах
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class MultiFormatDemo {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2025, 6, 1);
// Стандартный ISO
System.out.println(date.format(DateTimeFormatter.ISO_LOCAL_DATE)); // 2025-06-01
// Кастомный формат
DateTimeFormatter rusFormat = DateTimeFormatter.ofPattern("dd.MM.yyyy");
System.out.println(date.format(rusFormat)); // 01.06.2025
// Английский стиль
DateTimeFormatter usFormat = DateTimeFormatter.ofPattern("MM/dd/yyyy");
System.out.println(date.format(usFormat)); // 06/01/2025
}
}
Форматирование времени
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
public class TimeFormatDemo {
public static void main(String[] args) {
LocalTime time = LocalTime.of(14, 30, 5);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
System.out.println(time.format(formatter)); // 14:30:05
}
}
5. Парсинг: превращаем строку в дату/время
Общая схема
- Получаем строку (например, от пользователя).
- Создаём форматтер с тем же шаблоном, что и у строки.
- Вызываем статический метод parse() или метод parse() объекта форматтера.
Пример: парсинг даты
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class ParseDateDemo {
public static void main(String[] args) {
String input = "01.06.2025";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
LocalDate date = LocalDate.parse(input, formatter);
System.out.println(date); // 2025-06-01
}
}
Пример: парсинг даты и времени
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class ParseDateTimeDemo {
public static void main(String[] args) {
String input = "01.06.2025 14:30";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");
LocalDateTime dateTime = LocalDateTime.parse(input, formatter);
System.out.println(dateTime); // 2025-06-01T14:30
}
}
6. Обработка ошибок парсинга
Парсинг — штука коварная. Если строка не подходит под шаблон, Java выбросит исключение DateTimeParseException. Это обычная ситуация, например, если пользователь ввёл дату с ошибкой.
Пример: обработка ошибок при парсинге
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
public class ParseErrorDemo {
public static void main(String[] args) {
String input = "32.13.2025"; // Некорректная дата
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
try {
LocalDate date = LocalDate.parse(input, formatter);
System.out.println(date);
} catch (DateTimeParseException ex) {
System.out.println("Ошибка парсинга: " + ex.getMessage());
}
}
}
Важно: всегда обрабатывайте такие ошибки, если работаете с пользовательским вводом!
7. Практика: преобразование дат для пользователя
Допустим, в нашем учебном приложении есть задача: пользователь вводит дату рождения в формате "дд.ММ.гггг", а программа должна вывести дату в формате "yyyy/MM/dd", а также день недели.
Пример
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Scanner;
public class BirthdayFormatDemo {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Введите дату рождения (дд.ММ.гггг): ");
String input = scanner.nextLine();
DateTimeFormatter inputFormat = DateTimeFormatter.ofPattern("dd.MM.yyyy");
DateTimeFormatter outputFormat = DateTimeFormatter.ofPattern("yyyy/MM/dd");
try {
LocalDate birthday = LocalDate.parse(input, inputFormat);
String formatted = birthday.format(outputFormat);
System.out.println("Ваша дата в новом формате: " + formatted);
System.out.println("День недели: " + birthday.getDayOfWeek()); // Например, SATURDAY
} catch (DateTimeParseException ex) {
System.out.println("Ошибка: некорректный формат даты!");
}
}
}
8. Локализация: как язык влияет на форматирование
С помощью DateTimeFormatter можно не только менять порядок чисел, но и выводить месяц словами, день недели и т.д. При этом учитывается локаль (язык и регион).
Пример: вывод месяца словами на русском
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class LocaleDemo {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2025, 6, 1);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d MMMM yyyy", new Locale("ru"));
System.out.println(date.format(formatter)); // 1 июня 2025
}
}
Пример: английская локаль
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class LocaleEnDemo {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2025, 6, 1);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d MMMM yyyy", Locale.ENGLISH);
System.out.println(date.format(formatter)); // 1 June 2025
}
}
Лайфхак: если хотите, чтобы месяц и день недели были на нужном языке — указывайте локаль явно!
9. Типичные ошибки при форматировании и парсинге дат
Ошибка № 1: Несоответствие шаблона и строки.
Если строка "01.06.2025 14:30", а шаблон "dd.MM.yyyy", парсинг завершится ошибкой. Шаблон должен точно совпадать со строкой.
Ошибка № 2: Перепутаны символы шаблона.
MM — месяц, mm — минуты. Если написать "dd.mm.yyyy", Java решит, что вы хотите минуты, и выдаст ошибку. Для месяца всегда используйте заглавные M.
Ошибка № 3: Необработанные исключения при парсинге.
Если не ловить DateTimeParseException, программа может внезапно завершиться при неправильном вводе пользователя. Всегда обрабатывайте такие ошибки.
Ошибка № 4: Не указана локаль при использовании слов.
Если используете шаблон с месяцем словами (MMMM), а локаль не указана, Java может использовать язык по умолчанию (например, английский). Всегда явно задавайте нужную локаль.
Ошибка № 5: Использование старых классов (SimpleDateFormat, Date) в новых проектах.
Помните: в современном коде используйте только java.time и DateTimeFormatter.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ