JavaRush /Курсы /JAVA 25 SELF /Обзор java.time API, отличие от старых API

Обзор java.time API, отличие от старых API

JAVA 25 SELF
13 уровень , 1 лекция
Открыта

1. Исторический контекст: как работали с датами до Java 8

В далёкой древности (до Java 8) для работы с датами и временем использовали классы java.util.Date, java.util.Calendar и для форматирования — java.text.SimpleDateFormat. Это был тот случай, когда программисты всей планеты дружно вздыхали и, скрипя зубами, писали что-то вроде:

import java.util.Date;

Date now = new Date();
System.out.println(now); // Выведет что-то странное вроде "Wed Jun 05 14:15:22 MSK 2025"

Звучит просто, но на деле всё было не так радужно. Вот лишь некоторые "радости" старого API:

  • Date — изменяемый (mutable) объект. Его можно было случайно поменять, и это часто приводило к багам.
  • Месяцы в Date и Calendar начинались с нуля (январь — это 0, декабрь — 11), а дни — с единицы.
  • SimpleDateFormat не был потокобезопасным: если два потока форматировали дату одновременно, можно было получить неожиданные результаты.
  • Огромное количество методов было объявлено как @Deprecated (устаревшие), и IDE постоянно пугала вас жёлтыми предупреждениями.
  • Работа с часовыми поясами была настоящей болью: легко было перепутать локальное время и UTC, а про переход на летнее/зимнее время лучше вообще не вспоминать.

Пример боли

import java.util.Date;

Date date = new Date(2025, 5, 1); // 2025 год, 5 месяц (июнь?), 1 число
System.out.println(date); // Не то, что ожидаешь!

2. Появление java.time: новый подход

К 2014 году стало понятно: старый API не просто неудобен — он опасен. Поэтому в Java появился новый пакет — java.time, реализующий спецификацию JSR‑310. Этот API был вдохновлён популярной библиотекой Joda-Time и сразу стал стандартом де‑факто.

Основные пакеты и классы

  • java.time — основной пакет, где живут все новые классы для дат и времени.
  • java.time.format — для форматирования и парсинга дат и времени.
  • java.time.temporal — для более продвинутых временных операций.
  • java.time.zone — для работы с часовыми поясами.

Вот главные герои нового API:

Класс Для чего? Пример использования
LocalDate
Только дата (год, месяц, день) День рождения, без времени
LocalTime
Только время (часы, минуты, секунды) Время встречи, без даты
LocalDateTime
Дата и время, без часового пояса Локальное событие
ZonedDateTime
Дата и время с учётом таймзоны Встреча в Минске по местному времени
Instant
Абсолютная точка времени (UTC) Метка события в журнале
Duration
Промежуток времени (часы, минуты, сек.) Длительность звонка
Period
Период (годы, месяцы, дни) Стаж работы, возраст

Пример: создание даты по‑новому

import java.time.LocalDate;

LocalDate today = LocalDate.now();
System.out.println(today); // Например, "2025-06-05"

3. Преимущества нового API

Неизменяемость (immutable)

Все классы из java.time — неизменяемые. Это значит: если вы создали объект LocalDate, изменить его нельзя. Любая операция (например, добавить день) возвращает новый объект.

LocalDate today = LocalDate.now();
LocalDate tomorrow = today.plusDays(1);

System.out.println(today);    // 2025-06-05
System.out.println(tomorrow); // 2025-06-06

Явная работа с часовыми поясами

В старом API легко было забыть, в каком часовом поясе находится дата. В java.time всё явно: если нужен часовой пояс — используйте ZonedDateTime, если не нужен — используйте LocalDateTime.

import java.time.ZonedDateTime;
import java.time.ZoneId;

ZonedDateTime MinskTime = ZonedDateTime.now(ZoneId.of("Europe/Minsk"));
System.out.println(MinskTime); // 2025-06-05T14:23:45+03:00[Europe/Minsk]

Удобные методы для вычислений и сравнения

LocalDate today = LocalDate.now();
LocalDate nextMonth = today.plusMonths(1);
boolean isAfter = LocalDate.now().plusDays(1).isAfter(today); // true

Форматирование и парсинг

Форматирование и парсинг — через DateTimeFormatter (подробно — на следующей лекции):

import java.time.format.DateTimeFormatter;

LocalDate today = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
String formatted = today.format(formatter); // "05.08.2025"

4. Совместимость: как жить со старым кодом

В реальном мире очень часто приходится работать с библиотеками или старыми системами, где используются Date и Calendar. К счастью, новый API дружелюбен к наследию: можно конвертировать старые типы в новые и наоборот.

Преобразование DateInstant

import java.util.Date;
import java.time.Instant;

// Date → Instant
Date legacyDate = new Date();
Instant instant = legacyDate.toInstant();

// Instant → Date
Date dateBack = Date.from(instant);

Преобразование CalendarZonedDateTime

import java.util.Calendar;
import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.util.Date;

// Calendar → ZonedDateTime
Calendar calendar = Calendar.getInstance();
ZonedDateTime zdt = ZonedDateTime.ofInstant(
        calendar.toInstant(),
        calendar.getTimeZone().toZoneId()
);

// ZonedDateTime → Calendar
Calendar calBack = Calendar.getInstance();
calBack.setTime(Date.from(zdt.toInstant()));

Таблица: сопоставление старых и новых классов

Старый класс Новый класс Комментарий
java.util.Date
Instant
Абсолютное время
java.util.Calendar
ZonedDateTime
Дата и время с таймзоной
java.text.SimpleDateFormat
DateTimeFormatter
Форматирование/парсинг дат

5. Практика: первые шаги с java.time

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

import java.time.LocalDate;

public class UserProfile {
    private String name;
    private LocalDate birthDate;

    public UserProfile(String name, LocalDate birthDate) {
        this.name = name;
        this.birthDate = birthDate;
    }

    public void printProfile() {
        System.out.println("Имя: " + name);
        System.out.println("Дата рождения: " + birthDate);
    }
}

public class Main {
    public static void main(String[] args) {
        UserProfile user = new UserProfile("Алиса", LocalDate.of(1998, 12, 25));
        user.printProfile();
    }
}

Вывод:

Имя: Алиса
Дата рождения: 1998-12-25

6. Сравнение: старый API vs новый API

Пример: добавить неделю к дате рождения

Старый способ (Date/Calendar):

import java.util.Calendar;

Calendar cal = Calendar.getInstance();
cal.set(1998, Calendar.DECEMBER, 25);
cal.add(Calendar.WEEK_OF_YEAR, 1);
System.out.println(cal.getTime()); // Муторно и неочевидно

Новый способ (java.time):

import java.time.LocalDate;

LocalDate birthDate = LocalDate.of(1998, 12, 25);
LocalDate nextWeek = birthDate.plusWeeks(1);
System.out.println(nextWeek); // 1999-01-01

В новом API код короче, проще и безопаснее.

7. Типичные ошибки при работе с java.time

Ошибка №1: забыли, что объекты неизменяемы.
Если вызвать date.plusDays(1); и не сохранить результат, исходная дата останется прежней.

Ошибка №2: путаница между LocalDate и LocalDateTime.
LocalDate хранит только дату (год, месяц, день), а LocalDateTime — ещё и время. Не перепутайте, если нужно обработать и часы, и минуты.

Ошибка №3: использование старых классов в новых проектах.
Если есть возможность — всегда используйте java.time. Старые классы нужны только для совместимости.

Ошибка №4: неправильная работа с часовыми поясами.
Если нужно хранить событие, важное для разных регионов, используйте ZonedDateTime или хотя бы Instant. LocalDateTime не содержит информации о временной зоне!

Ошибка №5: попытка напрямую сравнивать LocalDate и LocalDateTime.
Это разные типы данных, сравнивать их напрямую нельзя. Сначала приведите к одному типу.

1
Задача
JAVA 25 SELF, 13 уровень, 1 лекция
Недоступна
Отметка текущего дня в календаре 🗓️
Отметка текущего дня в календаре 🗓️
1
Задача
JAVA 25 SELF, 13 уровень, 1 лекция
Недоступна
Взгляд назад: какой день был вчера? ⏪
Взгляд назад: какой день был вчера? ⏪
1
Задача
JAVA 25 SELF, 13 уровень, 1 лекция
Недоступна
Заглядываем в будущее: какой день будет завтра? ⏩
Заглядываем в будущее: какой день будет завтра? ⏩
1
Задача
JAVA 25 SELF, 13 уровень, 1 лекция
Недоступна
Фиксация важного исторического момента 📜
Фиксация важного исторического момента 📜
Комментарии (4)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Anna Klushkina Уровень 66
13 июня 2026
⛏️ Тема отличная, но задачи слишком простые
Timofey Novitsky Уровень 36
8 мая 2026
В пакете java.time (LocalDateTime, LocalDate и др.) конструкторы сделаны приватными. Это значит, что создать объект через new напрямую нельзя, не повторяйте мою ошибку, используйте статический фабричный метод .of().Это стандарт.
German Malykh Уровень 31
22 сентября 2025
Задание Фиксация важного исторического момента 📜

LocalDateTime historicMoment = LocalDateTime.of(...);

// Реализация метода из LocalDateTime класса 
// (Все параметры даты указываются через запятую)

public static LocalDateTime of(int year, int month, int dayOfMonth, int hour, int minute) {
        LocalDate date = LocalDate.of(year, month, dayOfMonth);
        LocalTime time = LocalTime.of(hour, minute);
        return new LocalDateTime(date, time);
}
StepV Уровень 16
18 апреля 2026
Какой сложный путь, у меня так прокатило 😁

public class Solution {
    public static void main(String[] args) {
    LocalDateTime historicMoment = LocalDateTime.of(2022, 03, 20, 10, 0, 0);    
    System.out.println(historicMoment);    

    }
}