Дата и время ·
‹ Предыдущий Следующий ›
⏱ 5 минут чтения Обновлено: 2026-10-19

Класс LocalTime в Java: текущее время, форматирование и методы

Вызов LocalTime.of(23, 30).plusMinutes(45) вернёт не ошибку и не «24:15», а 00:15: время в LocalTime замкнуто в сутки, и после 23:59:59.999999999 отсчёт снова начинается с полуночи. При этом исходный объект не меняется — метод возвращает новый.

Класс LocalTime в Java (java.time.LocalTime) — неизменяемый потокобезопасный класс, который хранит время суток без даты и часового пояса: часы, минуты, секунды и наносекунды, например 13:45:30.123456789. Он появился в Java 8 вместе с остальным java.time API и подходит для расписаний, часов работы, будильников и любых значений вида «в 9 утра», где дата не важна. Текущее время в Java получают вызовом LocalTime.now().

Как создать LocalTime: of() и parse()

Объект LocalTime создаётся статическими фабричными методами — публичного конструктора у класса нет. LocalTime.of(часы, минуты) задаёт время с точностью до минуты, of(часы, минуты, секунды) — до секунды, of(часы, минуты, секунды, наносекунды) — полностью, а LocalTime.parse("08:15:30") разбирает строку.

import java.time.LocalTime;

public class LocalTimeExample1 {
    public static void main(String[] args) {
        // С часами (0-23) и минутами (0-59)
        LocalTime fiveThirty = LocalTime.of(5, 30);
        // С часами, минутами и секундами (0-59)
        LocalTime noon = LocalTime.of(12, 0, 0);
        // С часами, минутами, секундами и наносекундами (0-999 999 999)
        LocalTime almostMidnight = LocalTime.of(23, 59, 59, 999_999_999);
        // Из строки в формате ISO-8601
        LocalTime fromString = LocalTime.parse("08:15:30");

        System.out.println(fiveThirty);
        System.out.println(noon);
        System.out.println(almostMidnight);
        System.out.println(fromString);
    }
}
05:30
12:00
23:59:59.999999999
08:15:30

Обратите внимание на вывод: toString() не печатает нулевые секунды и наносекунды, поэтому LocalTime.of(12, 0, 0) выводится как 12:00. Доли секунды печатаются группами по три цифры: LocalTime.of(10, 0, 0, 1_000_000) даст 10:00:00.001.

999999 наносекунд — это не 999 миллисекунд

Четвёртый аргумент of() — именно наносекунды. Код LocalTime.of(23, 59, 59, 999999) даст 23:59:59.000999999, то есть меньше одной миллисекунды после 23:59:59. Чтобы получить «почти полночь», пишите 999_999_999 или берите константу LocalTime.MAX.

Метод of() проверяет значения сразу. Некорректное время не «перетекает» в следующий час, а вызывает исключение. Строка для parse() без форматтера должна быть в формате ISO-8601 с двузначными часами и минутами:

LocalTime.of(24, 0);      // DateTimeException: Invalid value for HourOfDay (valid values 0 - 23): 24
LocalTime.of(10, 60);     // DateTimeException: Invalid value for MinuteOfHour (valid values 0 - 59): 60
LocalTime.parse("9:30");  // DateTimeParseException: Text '9:30' could not be parsed at index 0
LocalTime.parse("25:00"); // DateTimeParseException: Text '25:00' could not be parsed: Invalid value for HourOfDay (valid values 0 - 23): 25

Строки в другом формате ("9:30", "07:05 PM") разбирают с шаблоном — см. раздел Форматирование LocalTime. Время можно построить и из числа секунд от полуночи — раздел toSecondOfDay() и ofSecondOfDay().

Текущее время в Java: LocalTime.now()

Чтобы получить текущее время в Java, вызовите LocalTime.now(). Метод возвращает время суток по системным часам в часовом поясе JVM по умолчанию, вместе с долями секунды; отдельные составляющие читают геттерами getHour(), getMinute(), getSecond() и getNano().

import java.time.LocalTime;

public class LocalTimeExample2 {
    public static void main(String[] args) {
        LocalTime now = LocalTime.now();
        int hour = now.getHour();
        int minute = now.getMinute();
        int second = now.getSecond();
        int nanosecond = now.getNano();

        System.out.println("Сейчас: " + now);
        System.out.println("Часы: " + hour);
        System.out.println("Минуты: " + minute);
        System.out.println("Секунды: " + second);
        System.out.println("Наносекунды: " + nanosecond);
    }
}
Сейчас: 14:07:52.381204    (зависит от момента запуска)
Часы: 14
Минуты: 7
Секунды: 52
Наносекунды: 381204000

Точность now() зависит от платформы: в Java 8 обычно миллисекунды, начиная с Java 9 — как правило микросекунды. Поэтому пользователю текущее время показывают отформатированным или усечённым методом truncatedTo(). Если нужны и время, и дата, используйте LocalDateTime.now().

У now() есть ещё два варианта. LocalTime.now(ZoneId.of("Asia/Tokyo")) вернёт текущее время в указанном часовом поясе, а LocalTime.now(clock) берёт время из объекта Clock: в продакшене это системные часы, а в тестах — фиксированные, и результат становится воспроизводимым:

import java.time.Clock;
import java.time.Instant;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZoneOffset;

public class LocalTimeNowExample {
    public static void main(String[] args) {
        Instant moment = Instant.parse("2024-03-15T10:00:00Z");

        System.out.println(LocalTime.now(Clock.fixed(moment, ZoneOffset.UTC)));
        System.out.println(LocalTime.now(Clock.fixed(moment, ZoneId.of("Asia/Tokyo"))));
    }
}
10:00
19:00

Константы MIN, MAX, MIDNIGHT и NOON

В LocalTime четыре готовые константы: MIN и MIDNIGHT — начало суток 00:00 (равные по значению), NOON — полдень 12:00, а MAX — последняя наносекунда суток 23:59:59.999999999. Значения «24:00» в LocalTime не существует.

Константа Значение Когда использовать
LocalTime.MIN 00:00 Нижняя граница интервала, «начало дня»
LocalTime.MIDNIGHT 00:00 То же значение, но название читается лучше, когда речь о полуночи
LocalTime.NOON 12:00 Разделение дня на «до полудня» и «после»
LocalTime.MAX 23:59:59.999999999 Верхняя граница интервала, «конец дня»

Получение часов, минут и секунд: get() и ChronoField

Кроме геттеров getHour()/getMinute(), у LocalTime есть универсальные методы get(TemporalField) и getLong(TemporalField) с константами ChronoField. Через них получают другие представления времени: час в 12-часовом формате, номер минуты или секунды в сутках, миллисекунды.

import java.time.LocalTime;
import java.time.temporal.ChronoField;

public class LocalTimeExample3 {
    public static void main(String[] args) {
        LocalTime time = LocalTime.of(13, 45, 30, 123_456_789);

        int hourAMPM = time.get(ChronoField.HOUR_OF_AMPM);          // 0-11
        int amPm = time.get(ChronoField.AMPM_OF_DAY);               // 0 - AM, 1 - PM
        int hourDay = time.get(ChronoField.HOUR_OF_DAY);            // 0-23
        int minuteDay = time.get(ChronoField.MINUTE_OF_DAY);        // 0-1439
        int minuteHour = time.get(ChronoField.MINUTE_OF_HOUR);      // 0-59
        int secondDay = time.get(ChronoField.SECOND_OF_DAY);        // 0-86399
        int secondMinute = time.get(ChronoField.SECOND_OF_MINUTE);  // 0-59
        int milli = time.get(ChronoField.MILLI_OF_SECOND);          // 0-999
        long nanoDay = time.getLong(ChronoField.NANO_OF_DAY);       // 0-86399999999999
        int nanoSecond = time.get(ChronoField.NANO_OF_SECOND);      // 0-999999999

        System.out.println("Часы (AM/PM): " + hourAMPM);
        System.out.println("До полудня (0) или после (1): " + amPm);
        System.out.println("Часы (0-23): " + hourDay);
        System.out.println("Минута в сутках: " + minuteDay);
        System.out.println("Минуты: " + minuteHour);
        System.out.println("Секунда в сутках: " + secondDay);
        System.out.println("Секунды: " + secondMinute);
        System.out.println("Миллисекунды: " + milli);
        System.out.println("Наносекунда в сутках: " + nanoDay);
        System.out.println("Наносекунды: " + nanoSecond);
    }
}
Часы (AM/PM): 1
До полудня (0) или после (1): 1
Часы (0-23): 13
Минута в сутках: 825
Минуты: 45
Секунда в сутках: 49530
Секунды: 30
Миллисекунды: 123
Наносекунда в сутках: 49530123456789
Наносекунды: 123456789

Для NANO_OF_DAY нужен именно getLong(): значение до 86 399 999 999 999 не помещается в int, и time.get(ChronoField.NANO_OF_DAY) выбросит UnsupportedTemporalTypeException: Invalid field 'NanoOfDay' for get() method, use getLong() instead. Поля, которых у времени нет, тоже вызывают исключение: time.get(ChronoField.EPOCH_DAY) — UnsupportedTemporalTypeException: Unsupported field: EpochDay, ведь без даты номер дня узнать нельзя.

Сравнение времени: isBefore(), isAfter(), equals()

Два LocalTime сравнивают методами isBefore() и isAfter() (строго раньше и строго позже), а на равенство проверяют через equals(). Оператор == для этого не годится: он сравнивает ссылки. Метод compareTo() возвращает отрицательное число, ноль или положительное, поэтому LocalTime можно сортировать как Comparable.

import java.time.LocalTime;

public class CompareLocalTimeExample {
    public static void main(String[] args) {
        LocalTime fiveThirty = LocalTime.of(5, 30);
        LocalTime noon = LocalTime.of(12, 0, 0);
        LocalTime almostMidnight = LocalTime.of(23, 59, 59, 999_999_999);

        System.out.println("fiveThirty.isAfter(noon)? " + fiveThirty.isAfter(noon));
        System.out.println("fiveThirty.isBefore(noon)? " + fiveThirty.isBefore(noon));
        System.out.println("noon.equals(almostMidnight)? " + noon.equals(almostMidnight));
        System.out.println("fiveThirty.compareTo(noon): " + fiveThirty.compareTo(noon));
        System.out.println("noon.compareTo(noon): " + noon.compareTo(noon));
    }
}
fiveThirty.isAfter(noon)? false
fiveThirty.isBefore(noon)? true
noon.equals(almostMidnight)? false
fiveThirty.compareTo(noon): -1
noon.compareTo(noon): 0

Частая практическая задача — проверить, попадает ли время в интервал. Для рабочего дня с 9:00 до 18:00 условие «не раньше начала и строго раньше конца» записывается так:

LocalTime now = LocalTime.of(14, 30);
boolean isWorking = !now.isBefore(LocalTime.of(9, 0)) && now.isBefore(LocalTime.of(18, 0));
System.out.println(isWorking); // true

Если интервал переходит через полночь, например ночная тишина с 22:00 до 6:00, условие «между» не работает: начало позже конца. Здесь время подходит, если оно после начала или до конца:

LocalTime from = LocalTime.of(22, 0);
LocalTime to = LocalTime.of(6, 0);
LocalTime check = LocalTime.of(2, 0);

boolean isQuietTime = check.isAfter(from) || check.isBefore(to);
System.out.println(isQuietTime); // true

Метод equals() учитывает все поля, включая наносекунды: LocalTime.of(12, 0).equals(LocalTime.of(12, 0, 0)) даёт true, а 12:00:00 и 12:00:00.000000001 уже не равны.

Изменение времени методами with()

Методы withHour(), withMinute(), withSecond() и withNano() заменяют одну составляющую времени и возвращают новый объект; универсальный with(TemporalField, long) делает то же через ChronoField. Остальные поля остаются прежними, а исходный LocalTime не меняется.

import java.time.LocalTime;
import java.time.temporal.ChronoField;

public class WithLocalTimeExample {
    public static void main(String[] args) {
        LocalTime noon = LocalTime.of(12, 0, 0);

        LocalTime ten = noon.with(ChronoField.HOUR_OF_DAY, 10);
        LocalTime eight = noon.withHour(8);
        LocalTime twelveThirty = noon.withMinute(30);
        LocalTime thirtyTwoSeconds = noon.withSecond(32);

        // Можно использовать сцепление методов
        LocalTime secondsNano = noon.withSecond(20).withNano(999_999);

        System.out.println("ten: " + ten);
        System.out.println("eight: " + eight);
        System.out.println("twelveThirty: " + twelveThirty);
        System.out.println("thirtyTwoSeconds: " + thirtyTwoSeconds);
        System.out.println("secondsNano: " + secondsNano);
        System.out.println("noon не изменился: " + noon);
    }
}
ten: 10:00
eight: 08:00
twelveThirty: 12:30
thirtyTwoSeconds: 12:00:32
secondsNano: 12:00:20.000999999
noon не изменился: 12:00

Значение вне диапазона отклоняется: noon.withHour(25) выбросит DateTimeException: Invalid value for HourOfDay (valid values 0 - 23): 25.

Методы plus() и minus()

Чтобы прибавить или вычесть время, используют plusHours(), plusMinutes(), plusSeconds(), plusNanos() и парные minusHours(), minusMinutes(), minusSeconds(), minusNanos(). Универсальные plus(long, TemporalUnit) и plus(TemporalAmount) принимают ChronoUnit или объект Duration. Каждый вызов возвращает новый объект.

import java.time.Duration;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;

public class PlusMinusLocalTimeExample {
    public static void main(String[] args) {
        LocalTime fiveThirty = LocalTime.of(5, 30);
        // Добавление
        LocalTime sixThirty = fiveThirty.plusHours(1);
        LocalTime fiveForty = fiveThirty.plusMinutes(10);
        LocalTime plusSeconds = fiveThirty.plusSeconds(14);
        LocalTime plusNanos = fiveThirty.plusNanos(99_999_999);
        LocalTime sevenThirty = fiveThirty.plus(2, ChronoUnit.HOURS);
        LocalTime seven = fiveThirty.plus(Duration.ofMinutes(90));

        // Вычитание
        LocalTime fourThirty = fiveThirty.minusHours(1);
        LocalTime fiveTen = fiveThirty.minusMinutes(20);
        LocalTime minusSeconds = fiveThirty.minusSeconds(2);
        LocalTime minusNanos = fiveThirty.minusNanos(1);
        LocalTime fiveTwenty = fiveThirty.minus(10, ChronoUnit.MINUTES);

        System.out.println("sixThirty: " + sixThirty);
        System.out.println("fiveForty: " + fiveForty);
        System.out.println("plusSeconds: " + plusSeconds);
        System.out.println("plusNanos: " + plusNanos);
        System.out.println("sevenThirty: " + sevenThirty);
        System.out.println("seven: " + seven);

        System.out.println("fourThirty: " + fourThirty);
        System.out.println("fiveTen: " + fiveTen);
        System.out.println("minusSeconds: " + minusSeconds);
        System.out.println("minusNanos: " + minusNanos);
        System.out.println("fiveTwenty: " + fiveTwenty);
    }
}
sixThirty: 06:30
fiveForty: 05:40
plusSeconds: 05:30:14
plusNanos: 05:30:00.099999999
sevenThirty: 07:30
seven: 07:00
fourThirty: 04:30
fiveTen: 05:10
minusSeconds: 05:29:58
minusNanos: 05:29:59.999999999
fiveTwenty: 05:20

Главная особенность — переход через границу суток. У LocalTime нет даты, поэтому при выходе за 23:59:59.999999999 отсчёт идёт с нуля, а при вычитании ниже 00:00 — с конца суток. Исключения не будет.

Что выведет этот код?

System.out.println(LocalTime.of(23, 30).plusMinutes(45));
System.out.println(LocalTime.of(0, 15).minusMinutes(30));
System.out.println(LocalTime.of(10, 0).plusHours(25));
System.out.println(LocalTime.of(10, 0).plusHours(24));
00:15
23:45
11:00
10:00

Прибавление ровно 24 часов возвращает исходное время, а 25 часов — то же, что один час. Чтобы узнать, что при этом «перешагнули» через полночь, нужна дата, то есть LocalDateTime. Попытка прибавить к LocalTime дни, например plus(1, ChronoUnit.DAYS), закончится ошибкой UnsupportedTemporalTypeException: Unsupported unit: Days.

Форматирование LocalTime: DateTimeFormatter

Чтобы вывести LocalTime в нужном виде, вызовите time.format(DateTimeFormatter.ofPattern("HH:mm:ss")); обратная операция — LocalTime.parse(текст, formatter). В шаблоне HH — часы 00–23, hh — часы 01–12, mm — минуты, ss — секунды, SSS — миллисекунды, a — AM/PM. Полная таблица символов — в уроке Класс DateTimeFormatter.

import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class FormatLocalTimeExample {
    public static void main(String[] args) {
        LocalTime time = LocalTime.of(13, 45, 30, 123_456_789);

        System.out.println(time.format(DateTimeFormatter.ofPattern("HH:mm:ss")));
        System.out.println(time.format(DateTimeFormatter.ofPattern("HH:mm:ss.SSS")));
        System.out.println(time.format(DateTimeFormatter.ofPattern("hh:mm a", Locale.ENGLISH)));
        System.out.println(time.format(DateTimeFormatter.ISO_LOCAL_TIME));

        // Обратная операция: строка -> LocalTime
        LocalTime evening = LocalTime.parse("07:05 PM", DateTimeFormatter.ofPattern("hh:mm a", Locale.ENGLISH));
        LocalTime morning = LocalTime.parse("9:30", DateTimeFormatter.ofPattern("H:mm"));
        System.out.println(evening);
        System.out.println(morning);
    }
}
13:45:30
13:45:30.123
01:45 PM
13:45:30.123456789
19:05
09:30

Строку "9:30" вызов LocalTime.parse("9:30") не разберёт, потому что стандартный ISO-формат требует 09:30. Если часы приходят без ведущего нуля, задайте шаблон H:mm, как в примере выше.

HH или hh, и Locale для AM/PM

Шаблон hh:mm без маркера a не отличает 01:45 от 13:45, поэтому для 24-часового формата берите HH. Маркер a выводит «AM/PM» или локализованный вариант в зависимости от языка системы, так что для предсказуемого результата передавайте Locale явно.

Шаблон с датой для LocalTime не подходит: time.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) выбросит UnsupportedTemporalTypeException: Unsupported field: YearOfEra, ведь даты в объекте нет.

Отбрасываем доли секунды: truncatedTo()

Метод truncatedTo(ChronoUnit) обнуляет все поля младше указанной единицы и возвращает новое время. Он нужен, когда доли секунды мешают: при выводе, сравнении и записи в БД.

import java.time.LocalTime;
import java.time.temporal.ChronoUnit;

public class TruncatedToExample {
    public static void main(String[] args) {
        LocalTime time = LocalTime.of(13, 45, 30, 123_456_789);

        System.out.println(time.truncatedTo(ChronoUnit.MILLIS));
        System.out.println(time.truncatedTo(ChronoUnit.SECONDS));
        System.out.println(time.truncatedTo(ChronoUnit.MINUTES));
        System.out.println(time.truncatedTo(ChronoUnit.HOURS));
        System.out.println(time.truncatedTo(ChronoUnit.HALF_DAYS));
    }
}
13:45:30.123
13:45:30
13:45
13:00
12:00

Единицы больше суток не поддерживаются: truncatedTo(ChronoUnit.MONTHS) выбросит UnsupportedTemporalTypeException: Unit is too large to be used for truncation. Типичный сценарий — два значения now() почти никогда не равны из-за долей секунды, а после truncatedTo(ChronoUnit.MINUTES) их можно сравнивать «с точностью до минуты».

toSecondOfDay() и ofSecondOfDay()

Метод toSecondOfDay() возвращает количество секунд, прошедших с полуночи (от 0 до 86399), а LocalTime.ofSecondOfDay(long) выполняет обратное преобразование. Аналогичная пара для наносекунд — toNanoOfDay() и ofNanoOfDay(). Эти методы удобны, когда время хранят одним числом.

import java.time.LocalTime;

public class SecondOfDayExample {
    public static void main(String[] args) {
        System.out.println(LocalTime.of(1, 1, 1).toSecondOfDay());
        System.out.println(LocalTime.MAX.toSecondOfDay());
        System.out.println(LocalTime.MAX.toNanoOfDay());
        System.out.println(LocalTime.ofSecondOfDay(3661));
        System.out.println(LocalTime.ofNanoOfDay(1_000_000_000L));
    }
}
3661
86399
86399999999999
01:01:01
00:00:01

Значение 86400 (ровно сутки) недопустимо: LocalTime.ofSecondOfDay(86400) выбросит DateTimeException: Invalid value for SecondOfDay (valid values 0 - 86399): 86400. toSecondOfDay() отбрасывает доли секунды, поэтому у LocalTime.MAX получается 86399, а не 86400.

Сколько времени между двумя LocalTime

Разницу между двумя значениями считают через ChronoUnit.MINUTES.between(start, end) (или HOURS, SECONDS), через эквивалентный start.until(end, ChronoUnit.MINUTES) либо через Duration.between(start, end), который возвращает объект с часами, минутами и секундами. Подробнее о самом Duration — в уроке Класс Duration.

import java.time.Duration;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;

public class BetweenLocalTimeExample {
    public static void main(String[] args) {
        LocalTime start = LocalTime.of(9, 15);
        LocalTime end = LocalTime.of(17, 45);

        System.out.println(ChronoUnit.MINUTES.between(start, end));
        System.out.println(ChronoUnit.HOURS.between(start, end));
        System.out.println(Duration.between(start, end));
        // Конец раньше начала - результат отрицательный
        System.out.println(Duration.between(end, start));
    }
}
510
8
PT8H30M
PT-8H-30M

У LocalTime нет даты, поэтому метод не знает, что смена началась вчера. Для ночной смены ChronoUnit.MINUTES.between(LocalTime.of(22, 0), LocalTime.of(6, 0)) вернёт -960, а не ожидаемые 480 минут. Если разность отрицательна, прибавьте сутки: Duration.between(from, to).plusHours(24) даст PT8H. Для надёжных расчётов с переходом через полночь используйте LocalDateTime.

LocalTime, LocalDateTime, ZonedDateTime и Instant

Класс LocalTime хранит только время суток, LocalDateTime добавляет к нему дату, ZonedDateTime — ещё и часовой пояс, а Instant описывает точный момент на временной шкале UTC. «Во сколько открывается магазин» — LocalTime, «когда пройдёт встреча» — LocalDateTime или ZonedDateTime, «когда произошло событие» — Instant.

Класс Что хранит Пример значения Когда выбирать
LocalTime Время суток 10:30 Расписание, часы работы, будильник
LocalDate Только дата 2024-03-15 День рождения, срок оплаты
LocalDateTime Дата и время без зоны 2024-03-15T10:30 Событие в одном часовом поясе
ZonedDateTime Дата, время и зона 2024-03-15T10:30+03:00[Europe/Moscow] Встречи и рейсы между городами
Instant Момент на шкале UTC 2024-03-15T07:30:00Z Метки времени, логи, хранение в БД

LocalTime превращается в LocalDateTime методом atDate(LocalDate), обратно — через toLocalTime(). Чтобы получить момент Instant, нужна ещё и зона:

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;

public class LocalTimeConvertExample {
    public static void main(String[] args) {
        LocalTime time = LocalTime.of(10, 30);
        ZoneId moscow = ZoneId.of("Europe/Moscow");

        LocalDateTime dateTime = time.atDate(LocalDate.of(2024, 3, 15)); // LocalTime + LocalDate
        Instant instant = dateTime.atZone(moscow).toInstant();            // + зона -> момент
        LocalTime inMoscow = Instant.parse("2024-03-15T10:00:00Z")
                .atZone(moscow).toLocalTime();                            // Instant -> LocalTime

        System.out.println(dateTime);
        System.out.println(dateTime.toLocalTime());
        System.out.println(instant);
        System.out.println(inMoscow);
    }
}
2024-03-15T10:30
10:30
2024-03-15T07:30:00Z
13:00

LocalTime.now() и System.nanoTime()

LocalTime.now() отвечает на вопрос «который час?», а System.nanoTime() — на вопрос «сколько прошло?». Метод nanoTime() возвращает long наносекунд от произвольной точки отсчёта: само число не связано со временем суток и имеет смысл только как разность двух вызовов. Для замера скорости кода нужен именно он, а для показа времени пользователю — LocalTime.

long start = System.nanoTime();
// ... измеряемый код ...
long elapsedNanos = System.nanoTime() - start;
System.out.println("Прошло, мс: " + elapsedNanos / 1_000_000);

Показания nanoTime() не зависят от перевода системных часов (ручная настройка, синхронизация NTP), поэтому интервалы не «прыгают». Разность двух LocalTime.now() может даже оказаться отрицательной, если часы перевели назад или замер пришёлся на полночь. Если нужен момент времени объектом, а не числом, берите Instant.now() — см. урок Класс Instant.

Шпаргалка по методам LocalTime

Методы LocalTime делятся на группы: создание, чтение полей, сравнение, получение изменённой копии и преобразование. Все методы, которые «меняют» время, на самом деле возвращают новый объект.

Метод Что делает Граничный случай / ошибка
now(), now(ZoneId), now(Clock) Текущее время суток Зависит от зоны JVM; для тестов передавайте Clock
of(h, m), of(h, m, s), of(h, m, s, n) Время из частей of(24, 0) — DateTimeException
parse(text), parse(text, formatter) Разбор строки "9:30" без шаблона H:mm — DateTimeParseException
getHour(), getMinute(), getSecond(), getNano(), get(ChronoField) Составляющие времени get(ChronoField.EPOCH_DAY) — UnsupportedTemporalTypeException
isBefore(), isAfter(), equals(), compareTo() Сравнение Интервал через полночь проверяют условием «или»
withHour(), withMinute(), withSecond(), withNano(), with() Замена одного поля withHour(25) — DateTimeException
plusHours(), minusMinutes() и аналоги, plus(), minus() Прибавить или вычесть время За границей суток время «заворачивается»; DAYS — исключение
format(formatter) Строка по шаблону Шаблон с датой (yyyy) — исключение
truncatedTo(unit) Обнуляет поля младше единицы MONTHS и больше — исключение
toSecondOfDay(), ofSecondOfDay(), toNanoOfDay(), ofNanoOfDay() Время как число от полуночи и обратно ofSecondOfDay(86400) — DateTimeException
atDate(LocalDate) Превращает в LocalDateTime Зона по-прежнему не задана

Типичные промахи с LocalTime

Большинство ошибок с LocalTime сводятся к трём причинам: забытое присваивание результата, неверный шаблон и ожидание, что у времени есть дата.

Ошибка Что происходит Как правильно
time.plusHours(1); без присваивания Время не меняется — результат потерян time = time.plusHours(1);
time1 == time2 Сравниваются ссылки, а не значения time1.equals(time2)
LocalTime.of(23, 59, 59, 999999) Получается 23:59:59.000999999 999_999_999 или LocalTime.MAX
Шаблон hh:mm для 24-часового времени 13:45 выводится как 01:45 Шаблон HH:mm
Интервал 22:00–06:00 как isAfter(from) && isBefore(to) Всегда false isAfter(from) || isBefore(to)
Замер скорости кода через LocalTime.now() Неточно, зависит от перевода системных часов System.nanoTime()

Часто задаваемые вопросы

Как перевести LocalTime из одного часового пояса в другой?

Сам LocalTime зону не хранит, поэтому конвертируют через ZonedDateTime: LocalDate.now().atTime(time).atZone(ZoneId.of("Europe/Moscow")).withZoneSameInstant(ZoneId.of("Asia/Tokyo")).toLocalTime(). Дата нужна, потому что смещение зоны может зависеть от неё (летнее время). Если LocalTime.now() показывает не то время, что на ваших часах, проверьте зону JVM — ZoneId.systemDefault().

Как сохранить LocalTime в базу данных через JDBC?

Начиная с JDBC 4.2 передавайте объект напрямую: ps.setObject(1, time) и rs.getObject("start_time", LocalTime.class); тип столбца — TIME. Старый путь через java.sql.Time.valueOf(time) тоже работает, но теряет доли секунды.

Как отсортировать список LocalTime и найти самое позднее время?

LocalTime реализует Comparable, поэтому подходит Collections.sort(list) — от раннего времени к позднему: [18:00, 09:30, 12:00] станет [09:30, 12:00, 18:00]. Самое позднее время вернёт Collections.max(list), самое раннее — Collections.min(list). Как работает сравнение — в разделе Сравнение времени.

Как протестировать код, который вызывает LocalTime.now()?

Не вызывайте LocalTime.now() прямо в бизнес-логике: передайте в класс объект Clock и пишите LocalTime.now(clock). В продакшене подставляйте Clock.systemDefaultZone(), а в тесте — Clock.fixed(...), тогда результат не зависит от времени запуска. Пример — в разделе Текущее время в Java.

Практика по теме

Закрепите урок на задачах — у каждой есть уровень и оценка времени.

Все задачи модуля →

Видео объяснение

Предпочитаете видеоформат? Посмотрите этот урок с примерами и объяснениями.

Комментарии

Зарегистрируйтесь или войдите, чтобы иметь возможность оставить комментарий.