把 Google Protobuf Timestamp 转换为 LocalDate

1、概览

Protocol Buffer (Protobuf) 是一种用于序列化结构化数据的二进制格式。它是由 Google 开发的,并且被广泛应用于跨平台和跨语言的数据通信。Protocol Buffer 使用简洁、高效的编码方案,可以将结构化数据定义为消息类型,并生成针对不同编程语言的数据访问代码。这使得在不同的系统之间传输和解析数据变得更加简单和高效。Protocol Buffer 具有广泛的支持,包括 Java、C++、Python、Golang 等编程语言。

Protobuf Timestamp 类型代表一个时间点,与任何特定时区无关。本文将带你了解如何把 Protobuf Timestamp 实例转换为 Java 的本地时间类型,如 LocalDate

2、Maven 依赖

pom.xml 中添加 protobuf-java 依赖:

<dependency>
    <groupId>com.google.protobuf</groupId>
    <artifactId>protobuf-java</artifactId>
    <version>4.26.1</version>
</dependency>

该依赖提供了 Timestamp 和其他与 Protobuf 相关的类。

3、Timestamp 类

Protobuf Timestamp 类表示自 Unix 纪元以来的时间点。与时区或本地日历没有关系。

它表示的是某个时间点的秒数和纳秒数。下面是使用 Java Instant 对象计算当前时间戳的示例:

Instant currentTimestamp = Instant.now();

Timestamp timestamp = Timestamp.newBuilder()
  .setSeconds(currentTimestamp.getEpochSecond())
  .setNanos(currentTimestamp.getNano())
  .build();

如上,通过 Instant 对象计算时间戳。首先,创建一个 Instant 对象,表示给定点的日期和时间。然后,提取秒和纳秒,并将它们传递给 Timestamp 实例。

4、把 Timestamp 实例转换为 LocalDate

在将 Timestamp 转换为 LocalDate 时,必须考虑时区及其与 UTC 的相关偏移,以准确表示本地日期。要将 Timestamp 转换为 LocalDate,首先要创建一个具有特定秒和纳秒的 Timestamp 实例:

Timestamp ts = Timestamp.newBuilder()
  .setSeconds(1000000)      // 秒
  .setNanos(77886600)       // 纳秒
  .build();

既然 Instant 类是最适合表示时间点的方法,那么就创建一个接受 Timestamp 作为参数并将其转换为 LocalDate 的方法:

LocalDate convertToLocalDate(Timestamp timestamp) {
    Instant instant = Instant.ofEpochSecond(timestamp.getSeconds(), timestamp.getNanos());
    // "America/Montreal" 美帝的时区
    LocalDate time = instant.atZone(ZoneId.of("America/Montreal")).toLocalDate();
    return time;
}

如上,使用 ofEpochSecond() 方法从 Timestamp 创建了一个 Instant 对象,该方法将 Timestamp 中的秒和纳秒作为参数。

然后,使用 atZone() 方法将 Instant 对象转换为 LocalDate,该方法允许我们指定时区。这一点至关重要,因为它确保生成的 LocalDate 反映了时区偏移量。

注意,还可以使用系统默认时区:

LocalDate time = instant.atZone(ZoneId.systemDefault()).toLocalDate();

编写一个单元测试来断言逻辑:

@Test
void givenTimestamp_whenConvertedToLocalDate_thenSuccess() {
    Timestamp timestamp = Timestamp.newBuilder()
      .setSeconds(1000000000)
      .setNanos(778866000)
      .build();
    LocalDate time = TimestampToLocalDate.convertToLocalDate(timestamp);
    assertEquals(LocalDate.of(2001, 9, 9), time);
}

如上,断言转换后的 LocalDate 与预期结果一致。

5、总结

本文介绍了如何把 Protobuf Timestamp 实例转换为 Java 的本地时间类型,如 LocalDate


Ref:https://www.baeldung.com/java-convert-google-protocol-buffer-timestamp-localdate