Зачем использовать Clock в Java для управления временем в приложении?
Что проверяют
Понимаете ли вы, что текущее время это внешняя зависимость, такая же как база или сеть, и её надо уметь подменять. Следом обычно просят показать тест на логику с датами, например истечение подписки, и спрашивают, где в приложении создаётся сам Clock.
Как отвечать
java.time.Clock это абстрактный источник текущего момента и часового пояса, он появился в Java 8 вместе с пакетом java.time. Методы now() принимают его параметром: Instant.now(clock), LocalDate.now(clock), ZonedDateTime.now(clock). Без параметра они берут системные часы и зону по умолчанию, и код становится недетерминированным.
Готовые реализации:
Clock.systemUTC()иClock.systemDefaultZone(): настоящее время, для продакшена;Clock.fixed(instant, zone): время стоит на месте, основной инструмент в тестах;Clock.offset(base, duration): сдвиг относительно другого источника, удобно проверить «что будет через 31 день»;Clock.tick(base, duration): время с заданной точностью, например до секунды.
С Java 17 есть ещё интерфейс InstantSource: только момент времени, без зоны. Clock его реализует, и если зона сервису не нужна, зависимость можно объявить уже.
На практике Clock объявляют бином (в Spring это @Bean Clock clock() { return Clock.systemUTC(); }) и внедряют через конструктор. В тесте передают фиксированные часы, и проверка «токен истёк через 15 минут» перестаёт зависеть от того, когда запущена сборка. Заодно пропадают нестабильные тесты около полуночи и расхождения между ноутбуком разработчика в Москве и CI-сервером в UTC.
Где спотыкаются
Внедряют Clock, но в половине мест продолжают вызывать LocalDateTime.now() без аргумента. Подмена работает частично, и тест врёт.
Мерят длительность через Clock или System.currentTimeMillis(). Системное время может прыгнуть назад при синхронизации NTP, для интервалов нужен монотонный System.nanoTime().
Подменяют время статическими моками вроде mockStatic(LocalDateTime.class). Это хрупко, медленно и маскирует проблему дизайна, которую Clock решает напрямую.