JSR 310: Instant

JSR 310: Instant, image #1

Класс java.time.Instant описывает точное время и работает с метками времени в формате UTC. Для большинства технических задач, например, хранения, логгирования и аудита, Instant подходит лучше всего.

Получить экземпляр Instant можно при помощи InstantSource, Clock и следующих статических методов класса Instant:

  • now — текущая метка времени
  • parse — парсинг строки, содержащей метку времени
  • ofEpochSecond — на основе количества секунд с начала эпохи UNIX (полночь 1 января 1970 года)
  • ofEpochMilli — на основе количества миллисекунд с начала эпохи UNIX
  • from — на основе экземпляров других классов, описывающих точное время, таких как ZonedDateTime и OffsetDateTime
// Текущая метка времени
Instant.now();

// Текущая метка времени с использованием конкретных часов
Instant.now(Clock.systemDefaultZone());

// Парсинг метки времени
Instant.parse("2026-06-15T11:10:15.1234Z");

// По количеству секунд с начала эпохи UNIX
Instant.ofEpochSecond(1781506920578L);

// По количеству секунд с начала эпохи UNIX с наносекундами
Instant.ofEpochSecond(1781506920578L, 123456L);

// На основе ZonedDateTime
Instant.from(ZonedDateTime.now());

Единицы измерения и свойства времени

Instant поддерживает следующие единицы измерения времени:

  • NANOS — наносекунды
  • MICROS — микросекунды
  • MILLIS — миллисекунды
  • SECONDS — секунды
  • MINUTES — минуты
  • HOURS — час
  • HALF_DAYS — половины суток
  • DAYS — сутки

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

Проверить поддержку единицы измерения времени классом вы можете при помощи метода isSupported:

var now = Instant.parse("2026-06-15T14:33:12Z");

now.isSupported(ChronoUnit.NANOS);// вернёт true
now.isSupported(ChronoUnit.MONTHS);// вернёт false

Instant поддерживает всего 4 свойства даты/времени:

  • INSTANT_SECONDS — количество секунд с начала эпохи UNIX
  • NANO_OF_SECOND - наносекунды текущей метки времени
  • MICRO_OF_SECOND - микросекунды текущей метки времени
  • MILLI_OF_SECOND - миллисекунды текущей метки времени

Примеры использования:

var instant = Instant.parse("2026-06-15T14:33:12.123Z");

// Получение миллисекунд текущей миллисекунды
// Вернёт 123
instant.get(ChronoField.MILLI_OF_SECOND);

// Получение количества секунд с начала эпохи UNIX
instant.getLong(ChronoField.INSTANT_SECONDS);

Получение данных из Instant

Для получения частей метки времени могут быть использованы методы get и getLong, объявленные в интерфейсе TemporalAccessor, а так же методы getNano и getEpochSecond. При попытке получения не поддерживаемого свойства будет выброшено исключение UnsupportedTemporalTypeException.

Instant instant = Instant.parse("2026-06-15T14:33:12.123Z");

// Получение количества секунд с начала эпохи UNIX - 1781533992
instant.getEpochSecond();

// Получение наносекунд текущей метки времени - 123000000
instant.getNano();

// Получение миллисекунд текущей метки времени как int - 123
instant.get(ChronoField.MILLI_OF_SECOND);

// Получение наносекунд текущей метки времени как long - 123000000
instant.getLong(ChronoField.NANO_OF_SECOND);

// Выбросит исключение UnsupportedTemporalTypeException
instant.get(ChronoField.HOUR_OF_DAY);

Для получения частей метки времени так же может быть использован метод query:

Instant instant = Instant.parse("2026-06-15T14:33:12.123Z");
TemporalAccessor millisReader = temporal -> temporal.get(ChronoField.MILLI_OF_SECOND);

// Вернёт количество миллисекунд - 123
instant.query(millisReader);

Метод range позволяет получить информацию о возможном диапазоне значений той или иной части метки времени:

Instant instant = Instant.parse("2026-06-15T14:33:12.123Z");

// Вернёт Range с диапазоном значений от 0 до 999
instant.range(ChronoField.MILLI_OF_SECOND);

Метод

Данные

Результат

x.isAfter(y)

x > y

true

x.isAfter(y)

x < y

false

x.isAfter(y)

x == y

false

x.isBefore(y)

x > y

false

x.isBefore(y)

x < y

true

x.isBefore(y)

x == y

false

x.compareTo(y)

x > y

1

x.compareTo(y)

x < y

-1

x.compareTo(y)

x =⇒ y

x.equals(y)

x == y

true

x.equals(y)

x != y

false

Вычисление времени

Экземпляры класса Instant являются неизменяемыми, но класс предоставляет методы plus, minus, truncatedTo и with, которые возвращают копии текущего экземпляра класса с указанными изменениями.

Методы plus, plusNanos, plusMillis и plusSeconds используются для получения нового экземпляра Instant, значение которого будет больше исходного на указанный промежуток времени.

Метод plus имеет два варианта: plus(TemporalAmount amountToAdd) и plus(long amountToAdd, TemporalUnit unit). В первом случае могут быть использованы экземпляры классов java.time.Duration и java.time.Period, но стоит помнить, что максимальная единица времени, которую можно использовать — день:

Instant instant = Instant.parse("2026-06-15T14:33:12.123Z");

// Вернёт Instant, значение которого на сутки больше исходного
// 2026-06-16T14:33:12.123Z
instant.plus(Period.ofDays(1));

// Выбросит исключение UnsupportedTemporalTypeException
instant.plus(Period.ofMonths(1));

Методы plusNanos, plusMillis и plusSeconds добавляют указанное количество наносекунд, миллисекунд и секунд соответственно.

Для получения меток времени, значения которых меньше исходного используются методы minus, minusNanos, minusMillis и minusSeconds, сигнатуры которых аналогичны методам plus…​, а поведение — противоположно.

В качестве аргументов вызова методов plus…​ и minus…​ могут быть использованы отрицательные значения:

Instant instant = Instant.parse("2026-06-15T14:33:12.123Z");

// Вернёт Instant на секунду меньше исходного
// 2026-06-15T14:33:11.123Z
instant.plus(Duration.ofSeconds(-1));

// Вернёт Instant на день больше исходного
// 2026-06-16T14:33:12.123Z
instant.minus(-1, ChronoUnit.DAYS);

Для усечения метки времени используется метод truncatedTo, а в качестве аргумента вызова указывается единица измерения времени, до которой требуется усечь метку времени:

Instant instant = Instant.parse("2026-06-15T14:33:12.123Z");

// Вернёт 2026-06-15T00:00:00Z
instant.truncatedTo(ChronoUnit.DAYS);

Значение Instant может быть усечено до дней.

Кроме этого вы можете менять значения поддерживаемых свойств метки времени при помощи метода with:

Instant instant = Instant.parse("2026-06-15T14:33:12.999Z");

// Установит 123 в качестве количества миллисекунд
// 2026-06-15T14:33:12.123Z
instant.with(ChronoField.MILLI_OF_SECOND, 123);

Однако стоит помнить, что Instant поддерживает весьма ограниченное количество свойств, которые были описаны выше.

Несколько операций над Instant могут быть объединены при помощи перегруженной версии метода with(TemporalAdjuster):

Instant instant = Instant.parse("2026-06-15T14:33:12.999Z");
TemporalAdjuster temporalAdjuster = temporal -> temporal.plus(1, ChronoUnit.HOURS)
        .minus(5, ChronoUnit.MINUTES)
        .with(ChronoField.MILLI_OF_SECOND, 123);

// Вернёт метку времени на 55 минут большую исходной и с 123 миллисекундами
// 2026-06-15T15:28:12.123Z
instant.with(temporalAdjuster);

Впрочем, стоит помнить, что TemporalAdjuster работает с интерфейсом Temporal, а не с Instant.

Резюме

  • Instant работает с точным временем в UTC и лучше всего подходит для технических целей: хранения, логгирования и аудита данных
  • Instant поддерживает ограниченный набор свойств: количество секунд и наносекунд, прошедших с полуночи 1 января 1970 года
  • Instant опирается на физические единицы времени, максимальная из которых — день
  • При помощи методов get…​ вы можете получить части метки времени
  • Для сравнения экземпляров класса Instant могут быть использованы методы isBefore, isAfter, compareTo и equals
  • Экземпляры класса Instant неизменяемы, но при помощи методов plus…​, minus…​ и truncatedTo вы можете выполнять различные манипуляции над меткой времени, получая в результате новый экземпляр класса Instant
9 views·2 shares