protobuf typeに日付型のcom.google.protobuf.Timestampをつかってみた
protobufのtypeに日付型をつかいたいケースがあったので com.google.protobuf.Timestamp
をつかってみた。
google/protobuf
を覗いてみると公式に載っているtypeの他にも使えそうなものがあるので定義に迷ったときは一読をおすすめする。
ここからは順にprotoの定義からgrpc-server, grpc-clientにおけるcom.google.protobuf.Timestamp
の使い方をまとめていく。※コードはすべてkotlinで、grpc-javaをつかっている
protoの定義方法
protoファイルの抜粋になるが import
を追加してtypeを定義するだけで使える。
import "google/protobuf/timestamp.proto"; message TaskOutbound { uint32 task_id = 1; string title = 2; google.protobuf.Timestamp finishedAt = 3; google.protobuf.Timestamp createdAt = 4; google.protobuf.Timestamp updatedAt = 5; }
finishedAt, createdAt, updatedAtに google.protobuf.Timestamp
を定義していることが分かる。
protoの全体はこちらから確認できるので参考にしてほしい。
grpc-serverではどうするか
LocalDateTimeからgoogle.protobuf.Timestamp
の型へ変換しているコードは次のようになる。
private fun getOutbound(entity: Task): TaskOutbound { val builder = TaskOutbound.newBuilder() .setTaskId(entity.id!!) .setTitle(entity.title) .setCreatedAt(getTimestamp(entity.createdAt)) .setUpdatedAt(getTimestamp(entity.updatedAt)) if (entity.finishedAt != null) builder.setFinishedAt(getTimestamp(entity.finishedAt)) return builder.build() } private fun getTimestamp(date: LocalDateTime): Timestamp.Builder { return Timestamp.newBuilder().setSeconds(date.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()) }
grpc-serverはレスポンスを返すことになるが、google.protobuf.Timestamp
を適応したfinishedAt, createdAt, updatedAtはgoogle.protobuf.TimestampのBuilder
クラスのインスタンスオブジェクトをセットする必要がある。
grpc-clinetではどうするか
clientはserverから受け取ったgoogle.protobuf.Timestamp
の値をyyyy-MM-dd'T'HH:mm:ss'Z'
な文字列のString型でエンドポイントへ返却したい。コードは次のようになる。
data class TaskModel(val id: Long, val title: String, val finishedAt: String?, val createdAt: String, val updatedAt: String) { constructor(entity: TaskOutbound) : this( id = entity.taskId.toLong(), title = entity.title, finishedAt = entity.finishedAt.let { if (it != null) Instant.ofEpochMilli(it.seconds).atZone(ZoneId.systemDefault()).toLocalDateTime().convert(DateUtil.Format.FULL_UTC) else null }, createdAt = Instant.ofEpochMilli(entity.createdAt.seconds).atZone(ZoneId.systemDefault()).toLocalDateTime().convert(DateUtil.Format.FULL_UTC), updatedAt = Instant.ofEpochMilli(entity.updatedAt.seconds).atZone(ZoneId.systemDefault()).toLocalDateTime().convert(DateUtil.Format.FULL_UTC) ) }
google.protobuf.Timestamp
にはgetSeconds()
のメソッドが用意されていてUNIXタイムが取得できる。この値からエンドポイントに必要な型へ変換することができる。
まとめ
google.protobuf.Timestamp
のつかいかたをまとめた- Timestamp以外にも実案件につかえるtypeは他にもあるので機会があればまとめていきたい
コード
コードは次のレポジトリにコミットしてあるので良かったら確認してみてください。