Введение в работу с датами и временем в Java
Работа с датами и временем — одна из самых частых задач в разработке. Будь то логирование событий, расчёт сроков, фильтрация данных или отображение календаря — без уверенного владения временными API не обойтись. В Java долгое время использовались классы java.util.Date и java.util.Calendar, но они имели множество недостатков: мутабельность, неинтуитивный API, проблемы с потоками.
Начиная с Java 8, в язык был добавлен новый пакет java.time, основанный на стандарте ISO-8601. Он предлагает immutable (неизменяемые) и thread-safe классы, которые гораздо удобнее в использовании. В этой статье мы разберём как старые, так и новые подходы, а также покажем практические примеры кода.
1. Устаревшие классы: Date и Calendar
Несмотря на то, что использование Date и Calendar не рекомендуется в новых проектах, вы можете встретить их в легаси-коде. Рассмотрим основные моменты.
Класс java.util.Date
Класс Date представляет конкретный момент времени с точностью до миллисекунды. Он имеет множество устаревших методов.
import java.util.Date;
public class DateExample {
public static void main(String[] args) {
// Текущая дата и время
Date now = new Date();
System.out.println("Текущее время: " + now);
// Конструктор с миллисекундами (с 1 января 1970)
Date specificDate = new Date(1000000000000L);
System.out.println("Дата: " + specificDate);
// Сравнение дат
boolean after = now.after(specificDate);
System.out.println("now после specificDate? " + after);
}
}
Класс java.util.Calendar
Calendar — более гибкий, но всё ещё неудобный класс для манипуляции датами.
import java.util.Calendar;
public class CalendarExample {
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
// Установка конкретной даты
cal.set(2025, Calendar.MARCH, 15, 10, 30, 0);
System.out.println("Установленная дата: " + cal.getTime());
// Получение отдельных полей
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH) + 1; // Месяцы с 0
int day = cal.get(Calendar.DAY_OF_MONTH);
System.out.println("Год: " + year + ", Месяц: " + month + ", День: " + day);
// Добавление дней
cal.add(Calendar.DAY_OF_MONTH, 10);
System.out.println("Через 10 дней: " + cal.getTime());
}
}
Недостатки: мутабельность (методы изменяют сам объект), сложность работы с часовыми поясами, путаница с индексами месяцев.
2. Современный API: java.time (Java 8+)
Пакет java.time решает все проблемы старых классов. Основные классы:
- LocalDate — дата без времени (год, месяц, день);
- LocalTime — время без даты (часы, минуты, секунды, наносекунды);
- LocalDateTime — дата и время без часового пояса;
- ZonedDateTime — дата и время с часовым поясом;
- Instant — момент времени в UTC;
- Duration и Period — для работы с промежутками времени.
LocalDate — работа с датами
import java.time.LocalDate;
import java.time.Month;
public class LocalDateExample {
public static void main(String[] args) {
// Текущая дата
LocalDate today = LocalDate.now();
System.out.println("Сегодня: " + today);
// Конкретная дата
LocalDate specific = LocalDate.of(2025, Month.DECEMBER, 25);
System.out.println("Рождество: " + specific);
// Прибавление дней
LocalDate nextWeek = today.plusDays(7);
System.out.println("Через неделю: " + nextWeek);
// Сравнение
boolean isBefore = today.isBefore(specific);
System.out.println("Сегодня до Рождества? " + isBefore);
}
}
LocalTime — работа со временем
import java.time.LocalTime;
public class LocalTimeExample {
public static void main(String[] args) {
// Текущее время
LocalTime now = LocalTime.now();
System.out.println("Сейчас: " + now);
// Конкретное время
LocalTime meeting = LocalTime.of(14, 30, 0);
System.out.println("Встреча в: " + meeting);
// Вычитание часов
LocalTime oneHourAgo = now.minusHours(1);
System.out.println("Час назад: " + oneHourAgo);
}
}
LocalDateTime — дата и время вместе
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class LocalDateTimeExample {
public static void main(String[] args) {
// Текущие дата и время
LocalDateTime now = LocalDateTime.now();
System.out.println("Сейчас: " + now);
// Форматирование вывода
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss");
String formatted = now.format(formatter);
System.out.println("Отформатировано: " + formatted);
// Парсинг строки
String dateStr = "15.03.2025 10:30:00";
LocalDateTime parsed = LocalDateTime.parse(dateStr, formatter);
System.out.println("Распарсено: " + parsed);
}
}
3. Форматирование и парсинг дат
Класс DateTimeFormatter позволяет гибко управлять отображением и чтением дат. Он immutable и thread-safe.
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class FormattingExample {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2025, 3, 15);
// Предопределённые форматы
System.out.println("ISO: " + date.format(DateTimeFormatter.ISO_DATE));
System.out.println("BASIC_ISO: " + date.format(DateTimeFormatter.BASIC_ISO_DATE));
// Пользовательский формат
DateTimeFormatter custom = DateTimeFormatter.ofPattern("dd/MM/yyyy");
System.out.println("Пользовательский: " + date.format(custom));
// С названием месяца на русском
DateTimeFormatter russian = DateTimeFormatter.ofPattern("dd MMMM yyyy", new Locale("ru"));
System.out.println("На русском: " + date.format(russian));
// Парсинг
String input = "15-03-2025";
DateTimeFormatter parser = DateTimeFormatter.ofPattern("dd-MM-yyyy