Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Даты и время

Для дат и времени в Java есть пакет java.time. Его классы неизменяемые: любая операция возвращает новый объект, а исходный не меняется. Старые классы Date и Calendar вы встретите в давнем коде, но в новом их не используют.

LocalDate

LocalDate — дата без времени и часового пояса: год, месяц, день. Создать её можно методом of, а сегодняшнюю дату даёт now():

void main() {
    LocalDate birthday = LocalDate.of(1995, 3, 14);
 
    IO.println(birthday);
    IO.println(birthday.getYear());
    IO.println(birthday.getMonth());
    IO.println(birthday.getDayOfWeek());
}

Результат:

1995-03-14
1995
MARCH
TUESDAY

Месяцы нумеруются по-человечески — с 1 (январь), а не с нуля. По умолчанию дата выводится в формате ISO: год-месяц-день.

Время и дата со временем

LocalTime хранит только время, LocalDateTime — дату и время вместе:

void main() {
    LocalTime opening = LocalTime.of(9, 30);
    LocalDateTime meeting = LocalDateTime.of(2026, 10, 5, 14, 0);
 
    IO.println(opening);
    IO.println(meeting);
    IO.println(meeting.toLocalDate());
}

Результат:

09:30
2026-10-05T14:00
2026-10-05

Текущий момент дают LocalDate.now(), LocalTime.now() и LocalDateTime.now(). Их результат, конечно, меняется при каждом запуске, поэтому в примерах урока используются фиксированные даты.

Арифметика дат

Методы plusDays, minusMonths, plusWeeks и подобные возвращают новую дату. Java сама учитывает длину месяцев и високосные годы:

void main() {
    LocalDate date = LocalDate.of(2024, 1, 31);
 
    IO.println(date.plusDays(1));
    IO.println(date.plusMonths(1));
    IO.println(date.minusYears(1));
    IO.println(date.isLeapYear());
}

Результат:

2024-02-01
2024-02-29
2023-01-31
true

31 января плюс месяц — это 29 февраля: такого числа, как 31 февраля, нет, и Java берёт последний день месяца.

Сколько прошло

Чтобы посчитать разницу между датами, используют ChronoUnit — он выдаёт число в нужных единицах. Period раскладывает разницу на годы, месяцы и дни, а Duration измеряет время в часах, минутах и секундах:

void main() {
    LocalDate start = LocalDate.of(2026, 1, 15);
    LocalDate end = LocalDate.of(2026, 10, 4);
 
    IO.println(ChronoUnit.DAYS.between(start, end) + " дн.");
 
    Period period = Period.between(start, end);
    IO.println(period.getMonths() + " мес. " + period.getDays() + " дн.");
 
    Duration lesson = Duration.between(LocalTime.of(10, 0), LocalTime.of(11, 35));
    IO.println(lesson.toMinutes() + " мин.");
}

Результат:

262 дн.
8 мес. 19 дн.
95 мин.

Сравнивать даты помогают isBefore, isAfter и isEqual.

Часовые пояса

LocalDateTime не знает, в каком городе происходит событие. Для этого есть ZonedDateTime — дата и время в конкретном часовом поясе. Метод withZoneSameInstant показывает тот же момент в другом поясе:

void main() {
    ZonedDateTime call = ZonedDateTime.of(
            LocalDateTime.of(2026, 10, 5, 18, 0), ZoneId.of("Europe/Berlin"));
 
    IO.println(call);
    IO.println(call.withZoneSameInstant(ZoneId.of("Asia/Tokyo")));
}

Результат:

2026-10-05T18:00+02:00[Europe/Berlin]
2026-10-06T01:00+09:00[Asia/Tokyo]

Для отметок времени в журналах и базах данных используют Instant — точку на шкале времени в UTC, без пояса.

Частая ошибка

Объекты java.time неизменяемы, поэтому вызов plusDays без присваивания ничего не меняет:

void main() {
    LocalDate deadline = LocalDate.of(2026, 10, 4);
    deadline.plusDays(7);
 
    IO.println(deadline);
}

Результат:

2026-10-04

Ошибки компиляции нет, но результат потерян. Правильно — сохранить новую дату: deadline = deadline.plusDays(7);.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.