Instant 是 Java 8 引入的日期时间 API,用于表示时间轴上的一个精确瞬间,以 UTC 时间为基准,精确到纳秒级别。它适用于需要高精度时间戳的场景,如日志记录、事件排序等。
Instant 的特性
基于 Unix 时间戳(从 1970-01-01T00:00:00Z 开始计算的秒数 / 纳秒数)
不可变类(线程安全)
以 UTC 时区为基础,不直接包含时区信息
精度可达纳秒(比传统的 System.currentTimeMillis() 精度更高)
Instant 应用场景:
生成高精度时间戳(如分布式系统中的事件排序)
日志记录中的时间标记
时间戳的持久化存储(数据库字段)
跨时区系统的时间统一表示
获取当前 UTC 时间的瞬时点,默认使用 Clock.systemUTC() 作为时钟源。示例:
Instant now = Instant.now(); // 输出格式: 2025-09-19T14:30:25.123456789Z
使用指定的时钟源获取当前时间(用于测试或特殊时钟需求),示例:
Instant now = Instant.now(Clock.systemDefaultZone());
通过毫秒级时间戳(自 1970-01-01T00:00:00Z 起)创建 Instant。若毫秒数超过 Long 范围会抛出ArithmeticException。示例:
Instant instant = Instant.ofEpochMilli(1726756225000L);
通过秒级时间戳创建 Instant(纳秒部分为 0),重载方法:
ofEpochSecond(long epochSecond, long nanoAdjustment)
可额外添加纳秒调整值(范围:0-999,999,999),示例:
Instant instant = Instant.ofEpochSecond(1726756225); // 仅秒级 Instant withNano = Instant.ofEpochSecond(1726756225, 500_000_000); // 加500毫秒
解析 ISO-8601 格式的字符串为 Instant。
支持格式:yyyy-MM-ddTHH:mm:ssZ、yyyy-MM-ddTHH:mm:ss.SSSZ等(带 Z 表示 UTC)。
示例:
Instant parsed = Instant.parse("2025-09-19T14:30:25.123Z");
从其他时间对象(如ZonedDateTime)转换为 Instant,示例:
Instant fromZoned = Instant.from(ZonedDateTime.now());
返回一个新的Instant,该Instant是在当前Instant的基础上加上指定的时间量。
参数 amountToAdd 是 TemporalAmount 类型,表示要添加的时间量。TemporalAmount 是一个接口,Duration 和 Period 都实现了该接口。通常可以使用 Duration 来表示基于时间单位(如秒、毫秒等)的时间量,使用 Period 来表示基于日期单位(如年、月、日等)的时间量。不过,Instant 主要用于表示时间线上的瞬时点,所以一般配合 Duration 使用。
示例代码:
import java.time.Duration; import java.time.Instant; public class InstantExample { public static void main(String[] args) { Instant now = Instant.now(); Duration duration = Duration.ofSeconds(30); // 创建一个30秒的时间量 Instant newInstant = now.plus(duration); System.out.println("当前时间: " + now); System.out.println("加上30秒后的时间: " + newInstant); } }
运行结果:
当前时间: 2025-09-22T03:11:03.798460061Z 加上30秒后的时间: 2025-09-22T03:11:33.798460061Z
返回一个新的Instant,该Instant是在当前Instant的基础上加上指定数量的指定时间单位。
参数:
amountToAdd:long类型,表示要添加的时间单位的数量。
unit:TemporalUnit类型,表示要添加的时间单位,例如ChronoUnit.SECONDS(秒)、ChronoUnit.MILLIS(毫秒)等。ChronoUnit枚举类实现了TemporalUnit接口,提供了常用的时间单位。
示例代码:
import java.time.Instant; import java.time.temporal.ChronoUnit; public class InstantExample { public static void main(String[] args) { Instant now = Instant.now(); Instant newInstant = now.plus(60, ChronoUnit.SECONDS); // 加上60秒 System.out.println("当前时间: " + now); System.out.println("加上60秒后的时间: " + newInstant); } }
运行结果:
当前时间: 2025-09-22T03:11:30.926505633Z 加上60秒后的时间: 2025-09-22T03:12:30.926505633Z
返回一个新的Instant,该Instant是在当前Instant的基础上加上指定的毫秒数。
参数:
millisToAdd:long类型,表示要添加的毫秒数。
示例代码:
import java.time.Instant; public class InstantExample { public static void main(String[] args) { Instant now = Instant.now(); Instant newInstant = now.plusMillis(500); // 加上500毫秒 System.out.println("当前时间: " + now); System.out.println("加上500毫秒后的时间: " + newInstant); } }
运行结果:
当前时间: 2025-09-22T03:11:54.700640492Z 加上500毫秒后的时间: 2025-09-22T03:11:55.200640492Z
返回一个新的Instant,该Instant是在当前Instant的基础上加上指定的纳秒数。
参数:
nanosToAdd:long类型,表示要添加的纳秒数。
示例代码:
import java.time.Instant; public class InstantExample { public static void main(String[] args) { Instant now = Instant.now(); Instant newInstant = now.plusNanos(1000000000); // 加上1秒(10亿纳秒) System.out.println("当前时间: " + now); System.out.println("加上1秒后的时间: " + newInstant); } }
当前时间: 2025-09-22T03:12:16.570142391Z 加上1秒后的时间: 2025-09-22T03:12:17.570142391Z
返回一个新的Instant,该Instant是在当前Instant的基础上加上指定的秒数。
参数:
secondsToAdd:long类型,表示要添加的秒数。
示例代码:
import java.time.Instant; public class InstantExample { public static void main(String[] args) { Instant now = Instant.now(); Instant newInstant = now.plusSeconds(15); // 加上15秒 System.out.println("当前时间: " + now); System.out.println("加上15秒后的时间: " + newInstant); } }
当前时间: 2025-09-22T03:12:41.598468806Z 加上15秒后的时间: 2025-09-22T03:12:56.598468806Z
从当前Instant对象表示的时间点减去指定的时间量。TemporalAmount是一个接口,Period(用于表示年月日的时间量)和Duration(用于表示秒和纳秒的时间量)等类都实现了该接口。
示例代码:
import java.time.Duration; import java.time.Instant; public class InstantMinusExample { public static void main(String[] args) { Instant now = Instant.now(); Duration duration = Duration.ofHours(2); // 创建一个表示2小时的Duration Instant result = now.minus(duration); System.out.println("当前时间: " + now); System.out.println("减去2小时后的时间: " + result); } }
运行结果:
当前时间: 2025-09-22T03:13:11.730086485Z 减去2小时后的时间: 2025-09-22T01:13:11.730086485Z
从当前Instant对象表示的时间点减去指定数量的指定时间单位。TemporalUnit是一个接口,ChronoUnit枚举实现了该接口,提供了诸如NANOS(纳秒)、SECONDS(秒)、MINUTES(分钟)等标准时间单位。
示例代码:
import java.time.Instant; import java.time.temporal.ChronoUnit; public class InstantMinusUnitExample { public static void main(String[] args) { Instant now = Instant.now(); Instant result = now.minus(30, ChronoUnit.MINUTES); // 减去30分钟 System.out.println("当前时间: " + now); System.out.println("减去30分钟后的时间: " + result); } }
运行结果:
当前时间: 2025-09-22T03:14:09.252006766Z 减去30分钟后的时间: 2025-09-22T02:44:09.252006766Z
从当前Instant对象表示的时间点减去指定的毫秒数。
示例代码:
import java.time.Instant; public class InstantMinusMillisExample { public static void main(String[] args) { Instant now = Instant.now(); Instant result = now.minusMillis(5000); // 减去5000毫秒(即5秒) System.out.println("当前时间: " + now); System.out.println("减去5秒后的时间: " + result); } }
运行结果:
当前时间: 2025-09-22T03:14:30.572092882Z 减去5秒后的时间: 2025-09-22T03:14:25.572092882Z
从当前Instant对象表示的时间点减去指定的纳秒数。
示例代码:
import java.time.Instant; public class InstantMinusNanosExample { public static void main(String[] args) { Instant now = Instant.now(); Instant result = now.minusNanos(1_000_000_000L); // 减去1秒(1秒 = 10亿纳秒) System.out.println("当前时间: " + now); System.out.println("减去1秒后的时间: " + result); } }
运行结果:
当前时间: 2025-09-22T03:15:03.015218228Z 减去1秒后的时间: 2025-09-22T03:15:02.015218228Z
从当前Instant对象表示的时间点减去指定的秒数。
示例代码:
import java.time.Instant; public class InstantMinusSecondsExample { public static void main(String[] args) { Instant now = Instant.now(); Instant result = now.minusSeconds(10); // 减去10秒 System.out.println("当前时间: " + now); System.out.println("减去10秒后的时间: " + result); } }
运行结果:
当前时间: 2025-09-22T03:15:22.602329939Z 减去10秒后的时间: 2025-09-22T03:15:12.602329939Z
除了增加/减少时间方法外,还提供了一个通用调整方法,如下:
将当前 Instant 调整到目标时间对象。
参数:temporal是一个实现了Temporal接口的对象,表示要被调整的目标时间对象。常见的实现类有ZonedDateTime、LocalDateTime等。
返回值:返回一个Temporal类型的对象,是调整后的目标时间对象 。通常情况下,返回的就是传入的temporal对象本身,不过在方法执行过程中其内部状态会被修改以反映基于Instant的调整。
示例:
package com.hxstrive.java_date_time.instant; import java.time.*; public class InstantAdjustIntoExample1 { public static void main(String[] args) { // 创建一个Instant对象 Instant instant = Instant.now(); // 创建一个ZonedDateTime对象 ZonedDateTime zonedDateTime = ZonedDateTime.now(); // 使用adjustInto方法将Instant应用到ZonedDateTime ZonedDateTime adjustedZonedDateTime = (ZonedDateTime)instant.adjustInto(zonedDateTime); System.out.println("原始的ZonedDateTime: " + zonedDateTime); System.out.println("调整后的ZonedDateTime: " + adjustedZonedDateTime); } }
运行结果:
原始的ZonedDateTime: 2025-09-22T11:21:59.924099200+08:00[Asia/Shanghai] 调整后的ZonedDateTime: 2025-09-22T11:21:59.875718400+08:00[Asia/Shanghai]
转换为毫秒级时间戳(自 1970-01-01T00:00:00Z 起),若时间超出 Long 范围会抛出ArithmeticException异常。示例:
long timestamp = Instant.now().toEpochMilli(); // 等效于System.currentTimeMillis()
获取秒级时间戳(自 1970-01-01T00:00:00Z 起),示例:
long seconds = Instant.now().getEpochSecond();
获取当前秒内的纳秒数(范围:0-999,999,999),示例:
int nanos = Instant.now().getNano(); // 如500000000表示0.5秒
转换为指定时区的ZonedDateTime,示例:
ZonedDateTime shanghaiTime = Instant.now().atZone(ZoneId.of("Asia/Shanghai"));
转换为带指定偏移量的OffsetDateTime,示例:
OffsetDateTime beijingTime = Instant.now().atOffset(ZoneOffset.of("+08:00"));
判断当前 Instant 是否在目标时间之前,示例:
boolean isBefore = Instant.now().isBefore(Instant.parse("2030-01-01T00:00:00Z"));
判断当前 Instant 是否在目标时间之后,示例:
boolean isAfter = Instant.now().isAfter(Instant.parse("2020-01-01T00:00:00Z"));
比较两个 Instant 的先后,返回值为负数(当前早于参数)、0(相等)、正数(当前晚于参数)
示例:
int result = Instant.now().compareTo(Instant.parse("2025-01-01T00:00:00Z"));
判断两个 Instant 是否表示同一时间点(纳秒级精确匹配),仅当两个对象的秒数和纳秒数完全相同时返回 true。
获取指定时间字段(如NANO_OF_SECOND)的有效值范围,示例:
ValueRange range = Instant.now().range(ChronoField.NANO_OF_SECOND); // range的值为0-999999999
获取指定时间字段的值(仅支持INSTANT_SECONDS和NANO_OF_SECOND),示例:
long seconds = Instant.now().get(ChronoField.INSTANT_SECONDS);
执行时间查询(如判断是否为闰年,需结合时区),示例:
Boolean isLeapYear = Instant.now().query(TemporalQueries.localDate()) .isLeapYear();
Instant 本身不含时区信息,始终以 UTC 为准,如需转换为本地时间,需结合 ZoneId。例如:
ZonedDateTime zdt = instant.atZone(ZoneId.of("Asia/Shanghai"));
虽然 Instant 支持纳秒级,但系统时钟可能无法达到该精度(通常为毫秒或微秒),老版本数据库可能不支持纳秒存储,需酌情截断。
// 与java.util.Date互转 Date date = Date.from(instant); // Instant -> Date Instant instant = date.toInstant(); // Date -> Instant
Instant 不直接支持日 / 月 / 年的加减(因涉及时区和历法),如需处理日历日期,应先转换为 LocalDateTime 或 ZonedDateTime。