ZetCode

Java Instant 类

最后修改时间:2025 年 4 月 16 日

java.time.Instant 类表示 UTC 时间线上的一个点。它从 1970-01-01T00:00:00Z 的 epoch 开始测量时间。Instant 提供了纳秒精度来表示时间戳。

Instant 是不可变的且线程安全的。它通常用于记录事件、在数据库中存储时间戳以及测量时间间隔。该类使用机器时间,而不是像日期这样的时间概念。

Instant 类概述

Instant 提供了获取当前时间、解析字符串和执行计算的方法。关键操作包括比较 Instant、添加持续时间以及转换为其他时间类型。该类处理秒和纳秒的时间。

public final class Instant implements Temporal, TemporalAdjuster, 
    Comparable<Instant>, Serializable {
    public static Instant now();
    public static Instant ofEpochSecond(long epochSecond);
    public static Instant ofEpochMilli(long epochMilli);
    public static Instant parse(CharSequence text);
    public long getEpochSecond();
    public int getNano();
    public boolean isAfter(Instant otherInstant);
    public boolean isBefore(Instant otherInstant);
    public Instant plus(long amountToAdd, TemporalUnit unit);
    public Instant minus(long amountToSubtract, TemporalUnit unit);
}

上面的代码显示了 Instant 提供的关键方法。这些方法允许创建、比较和操作 Instant。该类提供高达纳秒的精度,同时保持与旧 API 的兼容性。

创建 Instant 对象

可以以多种方式创建 Instant 对象。最常见的方法是使用 now 获取当前时间,以及使用工厂方法获取特定的时间点。也支持从字符串解析。

Main.java
package com.zetcode; 

import java.time.Instant;

public class Main {

    public static void main(String[] args) {
        
        // Current instant
        Instant now = Instant.now();
        System.out.println("Current instant: " + now);
        
        // From epoch seconds
        Instant epochSec = Instant.ofEpochSecond(1_000_000);
        System.out.println("From epoch seconds: " + epochSec);
        
        // From epoch milliseconds
        Instant epochMilli = Instant.ofEpochMilli(1_000_000_000L);
        System.out.println("From epoch milliseconds: " + epochMilli);
        
        // From string
        Instant parsed = Instant.parse("2025-01-01T00:00:00Z");
        System.out.println("Parsed from string: " + parsed);
    }
}

此示例演示了创建 Instant 对象的不同方法。输出显示 ISO-8601 格式的时间戳。now 方法捕获当前时刻,并尽可能提供纳秒精度。

获取 Instant 组件

一个 Instant 可以分解为它的 epoch 秒和纳秒组件。这些值表示自 1970-01-01T00:00:00Z 以来的时间。这些方法对于与旧 API 的互操作性很有用。

Main.java
package com.zetcode; 

import java.time.Instant;

public class Main {

    public static void main(String[] args) {

        Instant instant = Instant.now();
        
        // Get epoch seconds
        long seconds = instant.getEpochSecond();
        System.out.println("Epoch seconds: " + seconds);
        
        // Get nanoseconds fraction
        int nanos = instant.getNano();
        System.out.println("Nanoseconds: " + nanos);
        
        // Convert to milliseconds (losing nanos precision)
        long millis = instant.toEpochMilli();
        System.out.println("Epoch milliseconds: " + millis);
    }
}

此示例展示了如何从 Instant 中提取组件。请注意,toEpochMilli 失去了纳秒精度,因为它转换为毫秒。epoch 秒和纳秒一起提供了完整的精度。

比较 Instants

可以比较 Instants 以确定时间顺序。该类提供了 isBeforeisAftercompareTo 方法。这些比较对于应用程序中基于时间的逻辑至关重要。

Main.java
package com.zetcode; 

import java.time.Instant;
import java.time.temporal.ChronoUnit;

public class Main {

    public static void main(String[] args) {

        Instant now = Instant.now();
        Instant later = now.plus(1, ChronoUnit.HOURS);
        Instant earlier = now.minus(30, ChronoUnit.MINUTES);
        
        System.out.println("Now is before later: " + now.isBefore(later));
        System.out.println("Now is after earlier: " + now.isAfter(earlier));
        System.out.println("Comparison result: " + now.compareTo(later));
        
        // Equality check
        Instant copy = Instant.ofEpochSecond(now.getEpochSecond(), now.getNano());
        System.out.println("Now equals copy: " + now.equals(copy));
    }
}

此示例演示了比较 Instant 对象的各种方法。比较方法同时考虑了秒和纳秒组件。请注意,相等需要两个组件完全匹配。

添加和减去时间

Instant 通过 plusminus 方法支持时间算术。这些操作对于计算未来或过去的时间点很有用。该类会自动处理溢出和下溢。

Main.java
package com.zetcode; 

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

public class Main {

    public static void main(String[] args) {

        Instant now = Instant.now();
        
        // Add using ChronoUnit
        Instant inOneHour = now.plus(1, ChronoUnit.HOURS);
        System.out.println("In one hour: " + inOneHour);
        
        // Subtract using Duration
        Instant thirtyMinsAgo = now.minus(Duration.ofMinutes(30));
        System.out.println("Thirty minutes ago: " + thirtyMinsAgo);
        
        // Add days (converted to seconds)
        Instant tomorrow = now.plus(1, ChronoUnit.DAYS);
        System.out.println("Tomorrow: " + tomorrow);
        
        // Mixed operations
        Instant complex = now.plus(2, ChronoUnit.HOURS)
                           .minus(15, ChronoUnit.MINUTES);
        System.out.println("Complex operation result: " + complex);
    }
}

此示例展示了使用 Instant 执行时间算术的各种方法。操作可以使用 ChronoUnit 常量或 Duration 对象。所有计算都精确到纳秒,并自动处理单位转换。

在时间类型之间转换

Instant 可以转换为其他时间类型,如 ZonedDateTime,也可以从其他时间类型转换。当处理时区或人类可读的日期表示时,这些转换至关重要。

Main.java
package com.zetcode; 

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class Main {

    public static void main(String[] args) {

        Instant now = Instant.now();
        
        // Convert to ZonedDateTime
        ZonedDateTime zoned = now.atZone(ZoneId.of("America/New_York"));
        System.out.println("In New York: " + zoned);
        
        // Convert to LocalDateTime (loses timezone info)
        LocalDateTime local = LocalDateTime.ofInstant(now, ZoneId.systemDefault());
        System.out.println("Local date-time: " + local);
        
        // Convert back to Instant
        Instant back = zoned.toInstant();
        System.out.println("Back to instant: " + back);
        
        // Convert from LocalDateTime
        Instant fromLocal = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant();
        System.out.println("From local date-time: " + fromLocal);
    }
}

此示例演示了 Instant 和其他时间类型之间的转换。请注意,LocalDateTime 缺少时区信息,因此使用系统默认值。所有转换都保留了所表示的确切时间点。

测量时间间隔

Instant 经常用于测量事件之间的时间间隔。Duration 类与 Instant 配合使用,以提供具有各种单位的精确时间测量。

Main.java
package com.zetcode; 

import java.time.Instant;
import java.time.Duration;

public class Main {

    public static void main(String[] args) throws InterruptedException {

        Instant start = Instant.now();
        
        // Simulate work
        Thread.sleep(1500);
        
        Instant end = Instant.now();
        
        // Calculate duration
        Duration duration = Duration.between(start, end);
        System.out.println("Elapsed time: " + duration.toMillis() + " ms");
        System.out.println("In seconds: " + duration.getSeconds() + "." + 
            duration.getNano() / 1_000_000 + " seconds");
        
        // Create duration and add to instant
        Duration twoHours = Duration.ofHours(2);
        Instant future = start.plus(twoHours);
        System.out.println("Two hours later: " + future);
    }
}

此示例展示了如何使用 Instant 和 Duration 测量时间间隔。Duration.between 方法计算精确的时间差。Duration 也可以用于使用 Instants 执行时间算术。

来源

Java Instant 类文档

在本文中,我们介绍了 Java Instant 类的基本方法和特性。理解这些概念对于在现代 Java 应用程序中进行精确的时间处理至关重要。

作者

我叫 Jan Bodnar,是一位经验丰富的程序员,在编程领域拥有多年经验。我从 2007 年开始撰写编程文章,此后撰写了 1,400 多篇文章和 8 本电子书。凭借超过八年的教学经验,我致力于分享我的知识并帮助他人掌握编程概念。

列出所有Java教程