Пакет java.time
Начиная с Java 8 для работы с датой и временем используется java.time. Старые Date и Calendar применять не стоит. Все классы java.time неизменяемы и потокобезопасны.
| Класс | Что хранит |
|---|---|
LocalDate | дата без времени и зоны |
LocalTime | время без даты и зоны |
LocalDateTime | дата и время без зоны |
ZonedDateTime | дата, время и часовой пояс |
Instant | момент на временной шкале (UTC) |
Duration | промежуток в секундах и наносекундах |
Period | промежуток в годах, месяцах, днях |
LocalDate
import java.time.DayOfWeek;import java.time.LocalDate;import java.time.Month;public class LocalDateDemo { public static void main(String[] args) { LocalDate today = LocalDate.now(); LocalDate date = LocalDate.of(2026, 10, 25); LocalDate parsed = LocalDate.parse("2026-12-31"); System.out.println(today.getYear() > 2000); System.out.println(date.getMonth()); System.out.println(date.getMonthValue()); System.out.println(date.getDayOfMonth()); System.out.println(date.getDayOfWeek()); System.out.println(date.getDayOfYear()); System.out.println(date.isLeapYear()); System.out.println(date.lengthOfMonth()); LocalDate nextWeek = date.plusDays(7); LocalDate lastMonth = date.minusMonths(1); LocalDate nextYear = date.plusYears(1); LocalDate firstOfMonth = date.withDayOfMonth(1); System.out.println(nextWeek + " " + lastMonth + " " + nextYear + " " + firstOfMonth); System.out.println(date.isBefore(parsed)); System.out.println(date.isAfter(parsed)); System.out.println(date.equals(LocalDate.of(2026, Month.OCTOBER, 25))); System.out.println(date.getDayOfWeek() == DayOfWeek.SUNDAY); }}Месяцы нумеруются с 1.
LocalTime и LocalDateTime
import java.time.LocalDate;import java.time.LocalDateTime;import java.time.LocalTime;public class LocalTimeDemo { public static void main(String[] args) { LocalTime time = LocalTime.of(14, 30, 15); System.out.println(time); System.out.println(time.plusHours(2)); System.out.println(time.minusMinutes(45)); System.out.println(time.isAfter(LocalTime.NOON)); LocalDateTime dateTime = LocalDateTime.of(2026, 10, 25, 9, 0); System.out.println(dateTime); System.out.println(dateTime.toLocalDate()); System.out.println(dateTime.toLocalTime()); System.out.println(LocalDateTime.of(LocalDate.of(2027, 1, 1), LocalTime.MIDNIGHT)); System.out.println(dateTime.plusDays(1).withHour(18)); }}Часовые пояса
import java.time.Instant;import java.time.LocalDateTime;import java.time.ZoneId;import java.time.ZonedDateTime;public class ZoneDemo { public static void main(String[] args) { ZonedDateTime berlin = ZonedDateTime.of( LocalDateTime.of(2026, 10, 25, 12, 0), ZoneId.of("Europe/Berlin") ); ZonedDateTime tokyo = berlin.withZoneSameInstant(ZoneId.of("Asia/Tokyo")); ZonedDateTime newYork = berlin.withZoneSameInstant(ZoneId.of("America/New_York")); System.out.println(berlin); System.out.println(tokyo); System.out.println(newYork); Instant instant = berlin.toInstant(); System.out.println(instant); System.out.println(instant.getEpochSecond()); System.out.println(Instant.ofEpochSecond(0)); System.out.println(ZoneId.systemDefault()); }}Для хранения и передачи моментов времени между системами используйте Instant или значения в UTC. Часовой пояс применяйте при показе пользователю.
Duration и Period
import java.time.Duration;import java.time.LocalDate;import java.time.LocalDateTime;import java.time.Period;import java.time.temporal.ChronoUnit;public class DurationDemo { public static void main(String[] args) { LocalDateTime start = LocalDateTime.of(2026, 10, 25, 9, 0); LocalDateTime end = LocalDateTime.of(2026, 10, 25, 17, 45); Duration duration = Duration.between(start, end); System.out.println(duration); System.out.println(duration.toHours()); System.out.println(duration.toMinutes()); System.out.println(duration.toMinutesPart()); LocalDate birth = LocalDate.of(1995, 3, 14); LocalDate now = LocalDate.of(2026, 10, 25); Period period = Period.between(birth, now); System.out.println(period.getYears() + " лет, " + period.getMonths() + " мес., " + period.getDays() + " дн."); System.out.println(ChronoUnit.DAYS.between(birth, now)); System.out.println(ChronoUnit.MONTHS.between(birth, now)); Duration custom = Duration.ofMinutes(90); System.out.println(custom.plusSeconds(30)); }}Duration измеряет время на уровне секунд и наносекунд, а Period — календарные единицы.
Форматирование и разбор
import java.time.LocalDate;import java.time.LocalDateTime;import java.time.format.DateTimeFormatter;import java.time.format.DateTimeParseException;import java.util.Locale;public class FormatDemo { public static void main(String[] args) { LocalDateTime dt = LocalDateTime.of(2026, 10, 25, 14, 5, 9); DateTimeFormatter f1 = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss"); DateTimeFormatter f2 = DateTimeFormatter.ofPattern("d MMMM yyyy, EEEE", Locale.forLanguageTag("ru")); System.out.println(dt.format(f1)); System.out.println(dt.format(f2)); System.out.println(dt.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); LocalDate parsed = LocalDate.parse("25.10.2026", DateTimeFormatter.ofPattern("dd.MM.yyyy")); System.out.println(parsed); try { LocalDate.parse("2026/10/25"); } catch (DateTimeParseException e) { System.out.println("Неверный формат: " + e.getParsedString()); } }}Основные символы шаблона:
| Символ | Значение | Пример |
|---|---|---|
yyyy | год | 2026 |
MM | месяц числом | 10 |
MMMM | название месяца | октября |
dd | день месяца | 25 |
EEEE | день недели | воскресенье |
HH | часы 0–23 | 14 |
hh | часы 1–12 | 02 |
mm | минуты | 05 |
ss | секунды | 09 |
a | AM/PM | PM |
Форматтеры потокобезопасны, их можно хранить в static final полях. В отличие от SimpleDateFormat.
Корректировщики дат
import java.time.DayOfWeek;import java.time.LocalDate;import java.time.temporal.TemporalAdjusters;public class AdjustersDemo { public static void main(String[] args) { LocalDate date = LocalDate.of(2026, 10, 25); System.out.println(date.with(TemporalAdjusters.firstDayOfMonth())); System.out.println(date.with(TemporalAdjusters.lastDayOfMonth())); System.out.println(date.with(TemporalAdjusters.next(DayOfWeek.MONDAY))); System.out.println(date.with(TemporalAdjusters.previousOrSame(DayOfWeek.FRIDAY))); System.out.println(date.with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY))); }}Измерение времени выполнения
import java.time.Duration;import java.time.Instant;public class Timing { public static void main(String[] args) { Instant start = Instant.now(); long sum = 0; for (int i = 0; i < 100_000_000; i++) { sum += i; } Duration elapsed = Duration.between(start, Instant.now()); System.out.println(sum); System.out.println(elapsed.toMillis() + " мс"); long t0 = System.nanoTime(); long t1 = System.nanoTime(); System.out.println((t1 - t0) + " нс"); }}Для замера интервалов используйте System.nanoTime() или Instant, а System.currentTimeMillis() лучше оставить для получения текущего времени.
Рабочие дни: пример
import java.time.DayOfWeek;import java.time.LocalDate;public class Workdays { static LocalDate addWorkdays(LocalDate start, int days) { LocalDate date = start; int added = 0; while (added < days) { date = date.plusDays(1); DayOfWeek day = date.getDayOfWeek(); if (day != DayOfWeek.SATURDAY && day != DayOfWeek.SUNDAY) { added++; } } return date; } public static void main(String[] args) { System.out.println(addWorkdays(LocalDate.of(2026, 10, 23), 5)); }}Устаревшие классы
В старом коде встречаются java.util.Date, Calendar, SimpleDateFormat. Они изменяемые, непотокобезопасные и неудобные. Преобразование к современному API:
import java.time.Instant;import java.time.ZoneId;import java.time.ZonedDateTime;import java.util.Date;public class LegacyDate { public static void main(String[] args) { Date legacy = new Date(); Instant instant = legacy.toInstant(); ZonedDateTime zoned = instant.atZone(ZoneId.systemDefault()); Date back = Date.from(instant); System.out.println(zoned.getYear() > 2000); System.out.println(back.equals(legacy)); }}