Instant(时间戳)

Instant 是 Java 8 引入的日期时间 API,用于表示时间轴上的一个精确瞬间,以 UTC 时间为基准,精确到纳秒级别。它适用于需要高精度时间戳的场景,如日志记录、事件排序等。

Instant 的特性

  • 基于 Unix 时间戳(从 1970-01-01T00:00:00Z 开始计算的秒数 / 纳秒数)

  • 不可变类(线程安全)

  • 以 UTC 时区为基础,不直接包含时区信息

  • 精度可达纳秒(比传统的 System.currentTimeMillis() 精度更高)

Instant 应用场景:

  • 生成高精度时间戳(如分布式系统中的事件排序)

  • 日志记录中的时间标记

  • 时间戳的持久化存储(数据库字段)

  • 跨时区系统的时间统一表示

   

常用方法及示例

获取当前时间

Instant.now()

获取当前 UTC 时间的瞬时点,默认使用 Clock.systemUTC() 作为时钟源。示例:

Instant now = Instant.now(); // 输出格式: 2025-09-19T14:30:25.123456789Z

Instant.now(Clock clock

使用指定的时钟源获取当前时间(用于测试或特殊时钟需求),示例:

Instant now = Instant.now(Clock.systemDefaultZone());

Instant.ofEpochMilli(long epochMilli)

通过毫秒级时间戳(自 1970-01-01T00:00:00Z 起)创建 Instant。若毫秒数超过 Long 范围会抛出ArithmeticException。示例:

Instant instant = Instant.ofEpochMilli(1726756225000L);

Instant.ofEpochSecond(long epochSecond)

通过秒级时间戳创建 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毫秒

Instant.parse(CharSequence text)

解析 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");

Instant.from(TemporalAccessor temporal)

从其他时间对象(如ZonedDateTime)转换为 Instant,示例:

Instant fromZoned = Instant.from(ZonedDateTime.now());

  

增加时间操作

Instant(时间戳)

plus(TemporalAmount amountToAdd)

返回一个新的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

plus(long amountToAdd, TemporalUnit unit)

返回一个新的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

plusMillis(long millisToAdd)

返回一个新的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

plusNanos(long nanosToAdd)

返回一个新的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

plusSeconds(long secondsToAdd)

返回一个新的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(时间戳)

minus(TemporalAmount amountToSubtract)

从当前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

minus(long amountToSubtract, TemporalUnit unit)

从当前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

minusMillis(long millisToSubtract)

从当前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

minusNanos(long nanosToSubtract)

从当前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

minusSeconds(long secondsToSubtract)

从当前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

  

通用调整

除了增加/减少时间方法外,还提供了一个通用调整方法,如下:

adjustInto(Temporal temporal)

将当前 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]

  

转换与时间戳获取

toEpochMilli()

转换为毫秒级时间戳(自 1970-01-01T00:00:00Z 起),若时间超出 Long 范围会抛出ArithmeticException异常。示例:

long timestamp = Instant.now().toEpochMilli(); // 等效于System.currentTimeMillis()

getEpochSecond()

获取秒级时间戳(自 1970-01-01T00:00:00Z 起),示例:

long seconds = Instant.now().getEpochSecond();

getNano()

获取当前秒内的纳秒数(范围:0-999,999,999),示例:

int nanos = Instant.now().getNano(); // 如500000000表示0.5秒

atZone(ZoneId zone)

转换为指定时区的ZonedDateTime,示例:

ZonedDateTime shanghaiTime = Instant.now().atZone(ZoneId.of("Asia/Shanghai"));

atOffset(ZoneOffset offset)

转换为带指定偏移量的OffsetDateTime,示例:

OffsetDateTime beijingTime = Instant.now().atOffset(ZoneOffset.of("+08:00"));

  

比较与判断方法

isBefore(Instant other)

判断当前 Instant 是否在目标时间之前,示例:

boolean isBefore = Instant.now().isBefore(Instant.parse("2030-01-01T00:00:00Z"));

isAfter(Instant other)

判断当前 Instant 是否在目标时间之后,示例:

boolean isAfter = Instant.now().isAfter(Instant.parse("2020-01-01T00:00:00Z"));

compareTo(Instant other)

比较两个 Instant 的先后,返回值为负数(当前早于参数)、0(相等)、正数(当前晚于参数)

示例:

int result = Instant.now().compareTo(Instant.parse("2025-01-01T00:00:00Z"));

equals(Object obj)

判断两个 Instant 是否表示同一时间点(纳秒级精确匹配),仅当两个对象的秒数和纳秒数完全相同时返回 true。

  

其他方法

range(TemporalField field)

获取指定时间字段(如NANO_OF_SECOND)的有效值范围,示例:

ValueRange range = Instant.now().range(ChronoField.NANO_OF_SECOND);
// range的值为0-999999999

get(TemporalField field)

获取指定时间字段的值(仅支持INSTANT_SECONDS和NANO_OF_SECOND),示例:

long seconds = Instant.now().get(ChronoField.INSTANT_SECONDS);

query(TemporalQuery<R> query)

执行时间查询(如判断是否为闰年,需结合时区),示例:

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

避免使用 plusDays() 等方法

Instant 不直接支持日 / 月 / 年的加减(因涉及时区和历法),如需处理日历日期,应先转换为 LocalDateTime 或 ZonedDateTime。

  

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
其他应用
公众号