Java 使用协议缓冲区序列化日期

Java 使用协议缓冲区序列化日期,java,protocol-buffers,Java,Protocol Buffers,因此,经过一些搜索,建议使用int64epoch 这一切都很好,但当与我的模型交互时,我想与实际的LocalDate对象交互,那么处理这个问题的策略是什么呢 我能想到的两种策略是: 将反序列化的模型转换为另一个不同的模型。这是创建一个额外的对象,我希望避免这种情况 编辑生成的模型。我找不到这方面的任何文档,所以这可能相当危险 这里的常见做法是什么?您不应该编辑生成的代码。在许多原因中,这是一个坏主意,您编辑的代码可能无法与Protobuf库的未来版本一起工作 一般来说,从int64转换为某种

因此,经过一些搜索,建议使用
int64
epoch

这一切都很好,但当与我的模型交互时,我想与实际的
LocalDate
对象交互,那么处理这个问题的策略是什么呢

我能想到的两种策略是:

  • 将反序列化的模型转换为另一个不同的模型。这是创建一个额外的对象,我希望避免这种情况
  • 编辑生成的模型。我找不到这方面的任何文档,所以这可能相当危险

这里的常见做法是什么?

您不应该编辑生成的代码。在许多原因中,这是一个坏主意,您编辑的代码可能无法与Protobuf库的未来版本一起工作

一般来说,从
int64
转换为某种
Date
对象比较便宜。我建议将数据保留为
int64
格式,只在需要时构建
LocalDate
对象


也就是说,维护一个单独的手写模型,并且只在解析/序列化时使用Protobuf类也是一种常见的做法。

我为所有日期/时间创建了一个通用解决方案:

message Timestamp {
    int64 seconds = 1;
    int32 nanos = 2;
}
使用以下转换器:

public static Timestamp fromLocalDate(LocalDate localDate) {
    Instant instant = localDate.atStartOfDay().toInstant(ZoneOffset.UTC);
    return Timestamp.newBuilder()
        .setSeconds(instant.getEpochSecond())
        .setNanos(instant.getNano())
        .build();
}

public static LocalDate toLocalDate(Timestamp timestamp) {
    return LocalDateTime.ofInstant(Instant.ofEpochSecond(timestamp.getSeconds(), timestamp.getNanos()), ZoneId.of("UTC"))
        .toLocalDate();
}

不需要创建自己的时间戳版本

您只需使用
google.protobuf.Timestamp
():

这是创建
Date
对象的标准(proto)方法

使用新的Java8时间API,很容易将
即时
转换为
google.Timestamp

LocalDate date = ...;
final Instant instant = java.sql.Timestamp.valueOf(date.atStartOfDay()).toInstant();        
Timestamp t = Timestamp.newBuilder().setSeconds(instant.getEpochSecond()).build();
请注意,Google protobuf lib包含
时间戳的助手:


编辑生成的代码是个坏主意。这使得维护变得困难。多年以后,当你离开的时候,有人会因为你这样做而诅咒你。那么创建另一个模型的常见做法是什么呢?根据我的经验,是的。我没有考虑编辑类定义本身,只是在它生成的类中添加一个接口,该接口上有一个默认方法来进行转换。
LocalDate date = ...;
final Instant instant = java.sql.Timestamp.valueOf(date.atStartOfDay()).toInstant();        
Timestamp t = Timestamp.newBuilder().setSeconds(instant.getEpochSecond()).build();