Введение в работу с датами и временем в Java
Работа с датами и временем — одна из самых частых задач в разработке приложений. Java предоставляет мощные инструменты для этой цели. Долгое время основным классом был java.util.Date, но он имел серьёзные недостатки: мутабельность, путаница с месяцами (начиная с 0) и отсутствие поддержки часовых поясов. С выходом Java 8 ситуация кардинально изменилась — появился новый Date/Time API (пакет java.time), который является потокобезопасным, иммутабельным и интуитивно понятным. В этой статье мы разберём оба подхода, но основной фокус сделаем на современном API.
1. Legacy API: Date и Calendar
Хотя использовать старые классы в новом коде не рекомендуется, вы можете столкнуться с ними в легаси-проектах. Рассмотрим основные моменты.
Класс Date
Класс java.util.Date представляет конкретный момент времени с точностью до миллисекунды. Он имеет множество устаревших методов.
import java.util.Date;
public class LegacyDateExample {
public static void main(String[] args) {
// Текущая дата и время
Date now = new Date();
System.out.println("Текущая дата: " + now);
// Дата по миллисекундам (с 1 января 1970 г.)
Date specificDate = new Date(1000000000000L);
System.out.println("Дата по timestamp: " + specificDate);
// Сравнение дат
Date earlier = new Date(0);
boolean isBefore = earlier.before(now); // true
System.out.println("Раньше? " + isBefore);
}
}
Класс Calendar
java.util.Calendar — более гибкий, но громоздкий инструмент. Позволяет манипулировать полями даты.
import java.util.Calendar;
public class CalendarExample {
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
// Установка конкретной даты: 25 декабря 2024 года
cal.set(2024, Calendar.DECEMBER, 25, 10, 30, 0);
System.out.println("Дата: " + cal.getTime());
// Добавление 2 недель
cal.add(Calendar.WEEK_OF_YEAR, 2);
System.out.println("Через 2 недели: " + cal.getTime());
// Получение отдельных полей
int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
int month = cal.get(Calendar.MONTH) + 1; // +1, так как январь = 0
System.out.println("День: " + dayOfMonth + ", Месяц: " + month);
}
}
Недостатки: мутабельность (метод add изменяет исходный объект), сложность форматирования, путаница с часовыми поясами.
2. Современный Date/Time API (Java 8+)
Пакет java.time включает ключевые классы: LocalDate, LocalTime, LocalDateTime, ZonedDateTime, Instant и другие. Все они иммутабельны и потокобезопасны.
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 newYear = LocalDate.of(2025, Month.JANUARY, 1);
System.out.println("Новый год: " + newYear);
// Арифметика дат
LocalDate nextWeek = today.plusWeeks(1);
LocalDate lastMonth = today.minusMonths(1);
System.out.println("Через неделю: " + nextWeek);
System.out.println("Месяц назад: " + lastMonth);
// Сравнение
boolean isAfter = today.isAfter(newYear); // false
System.out.println("Сегодня после Нового года? " + isAfter);
}
}
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 inTwoHours = now.plusHours(2);
LocalTime tenMinutesAgo = now.minusMinutes(10);
System.out.println("Через 2 часа: " + inTwoHours);
System.out.println("10 минут назад: " + tenMinutesAgo);
}
}
LocalDateTime — дата и время вместе
Объединяет LocalDate и LocalTime. Идеален для хранения событий без привязки к зоне.
import java.time.LocalDateTime;
public class LocalDateTimeExample {
public static void main(String[] args) {
// Текущие дата и время
LocalDateTime now = LocalDateTime.now();
System.out.println("Текущий момент: " + now);
// Конкретный момент
LocalDateTime specific = LocalDateTime.of(2024, 12, 25, 10, 30, 0);
System.out.println("Рождество: " + specific);
// Извлечение частей
LocalDate datePart = specific.toLocalDate();
LocalTime timePart = specific.toLocalTime();
System.out.println("Дата: " + datePart + ", Время: " + timePart);
}
}
3. Часовые пояса и Instant
Для работы с временными зонами используйте ZonedDateTime и ZoneId. Instant представляет момент на временной шкале (Unix timestamp).
ZonedDateTime и ZoneId
import java.time.ZonedDateTime;
import java.time.ZoneId;
public class ZoneExample {
public static void main(String[] args) {
// Текущее время в UTC
ZonedDateTime utcNow = ZonedDateTime.now(ZoneId.of("UTC"));
System.out.println("UTC: " + utcNow);
// Время в Москве
ZonedDateTime moscowTime = ZonedDateTime.now(ZoneId.of("Europe/Moscow"));
System.out.println("Москва: " + moscowTime);
// Преобразование между зонами
ZonedDateTime nyTime = moscowTime.withZoneSameInstant(ZoneId.of("America/New_York"));
System.out.println("Нью-Йорк: " + nyTime);
}
}
Instant — машинное время
Блоги
Рекомендаций по книгам
Читайте также
Интеграция WebAssembly и PHP: практическое руководство
Ловим баги в полете: мониторинг и логирование JavaScript приложений
Монорепозиторий с TypeScript: организация кода и лучшие практики
Работа с JSON в TypeScript: парсинг и сериализация данных
Конвертация String в int в Rust: полное руководство с примерами
Блоги
Рекомендаций по книгам
Читайте также
Монорепозиторий с TypeScript: организация кода и лучшие практики
Работа с JSON в TypeScript: парсинг и сериализация данных