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

时间:2015-03-30 14:53:41

标签: java protocol-buffers

因此经过一些搜索,建议使用int64时代。

这一切都很好,但在与我的模型交互时,我想与实际的LocalDate对象进行交互,那么处理这个对象的策略是什么?

我能想到的两个策略是:

  • 将反序列化模型转换为另一个不同的模型。这是创建一个额外的对象,我希望避免这种情况。
  • 编辑生成的模型。
  • 我找不到任何关于此的文件,因此可能风险很大

这里的常见做法是什么?

3 个答案:

答案 0 :(得分:8)

我选择为所有日期/时间创建通用解决方案:

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();
}

答案 1 :(得分:2)

无需创建自己的Timestamp版本。

您只需使用google.protobuf.Timestampsource):

import "google/protobuf/timestamp.proto";
message Application {
    google.protobuf.Timestamp date = 1;
}

它是创建Date个对象的标准(proto)方式。

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

LocalDate date = ...;
final Instant instant = java.sql.Timestamp.valueOf(date.atStartOfDay()).toInstant();        
Timestamp t = Timestamp.newBuilder().setSeconds(instant.getEpochSecond()).build();

请注意,Google已为Timestamp建立了一个帮助:

https://github.com/google/protobuf/blob/master/java/util/src/main/java/com/google/protobuf/util/Timestamps.java

答案 2 :(得分:1)

您永远不应该编辑生成的代码。这是一个坏主意的众多原因,您编辑的代码可能无法与未来版本的Protobuf库一起使用。

通常,从int64转换为某种Date对象很便宜。我建议将数据保留为int64格式,并且只在需要时按需构建LocalDate对象。

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