1. 概述

java.time.Instantjava.sql.Timestamp 都表示 UTC 时间轴上的一个时间点,换句话说,它们都表示自 Java 纪元时间(1970-01-01T00:00:00Z)以来的纳秒数。

在本篇快速教程中,我们将使用 Java 内置方法在两者之间进行转换。

2. InstantTimestamp 的相互转换

Instant 转换为 Timestamp

我们可以使用 Timestamp.from() 方法将 Instant 实例转换为 Timestamp

Instant instant = Instant.now();
Timestamp timestamp = Timestamp.from(instant);
assertEquals(instant.toEpochMilli(), timestamp.getTime());

Timestamp 转换为 Instant

反过来,可以使用 Timestamp.toInstant() 方法:

instant = timestamp.toInstant();
assertEquals(instant.toEpochMilli(), timestamp.getTime());

⚠️ 无论哪种方式,InstantTimestamp 都表示时间轴上的同一个时间点。

3. toString() 方法的行为差异

虽然两者表示相同的时间点,但调用 toString() 方法时的行为是不同的:

  • Instant.toString() 总是返回 UTC 时区的时间。
  • Timestamp.toString() 返回的是 本地时区的时间。

来看一个实际例子:

Instant (UTC):       2018-10-18T00:00:57.907Z
Timestamp (本地时区): 2018-10-18 05:30:57.907

在这个例子中,本地时区为 GMT+05:30,因此 timestamp.toString() 的输出比 instant.toString() 多了 5 小时 30 分钟。

✅ 虽然 toString() 输出不同,但它们表示的是 同一时间点

我们可以通过将 Timestamp 转换回 UTC 时区来验证这一点:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
formatter = formatter.withZone(TimeZone.getTimeZone("UTC").toZoneId());
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");

assertThat(formatter.format(instant)).isEqualTo(df.format(timestamp));

4. 总结

在这篇简短的文章中,我们学习了如何使用 Java 内置方法在 java.time.Instantjava.sql.Timestamp 之间进行转换,并了解了它们在 toString() 输出中因时区而产生的差异。

一如既往,完整的代码示例可以在 GitHub 上找到。


原始标题:Convert Between java.time.Instant and java.sql.Timestamp