API でのリクエスト、レスポンスのフィールドとして、タイムスタンプを定義したいときがあります。 しかし、Protocol Buffer の言語仕様上、Scalar として日付、時刻関連の型は定義されていません。このようなとき、どのように対処すれば良いでしょうか。
日付 + 時刻については google.protobuf.Timestamp
を使う
以下のように書けば良いです。
import "google/protobuf/timestamp.proto"; // The response message containing the greetings message HelloReply { google.protobuf.Timestamp timestamp = 1; string message = 2; }
ちょっと解説しておくと、時刻情報は確かに Protocol Buffer の Scalar 型としては定義されていません。しかし、それは必ずしも時刻を Protocol Buffer で扱えないことを意味しません。
実は、Protocol Buffer には Well-Known Types という組み込み型が定義されていまして、 Timestamp
型も存在しています。
このため、上記のように Well-known Types
の型定義を .proto ファイル上で import
してやれば、Protocol Buffer 上で時刻が扱えるようになります。
この TimeStamp
型の実際の定義は timestamp.proto に存在しますが、UNIX の epoch time とナノ秒を保持しているだけです。golang だと ptypes を使うことで、time.Time
や string
への変換も可能です。
message Timestamp { int64 seconds = 1; int32 nanos = 2; }
あるいは、string として定義する
TimeStamp
型は扱いづらい、Scalar が良い、というのであれば、string として定義しても良いと思います。 protocol buffer をやり取りするピア間で、フォーマットさえ合意しておけば問題にはならないと考えています。
実は、直近ではこちらの方法を採っていまして、RFC 3339 形式で表すようにしています。
int64 で定義する
秒の粒度しか使わないのであれば、 int64
で epoch time として定義しても良いんじゃないか。Timestamp
型も結局のところ epoch time だし。
string の話含め、timestamp という型情報が失われるのをどう見るか。
時刻は要らない、日付だけ扱いたい
Google でも自分で定義しているので、自分で定義したほうが良いのではないでしょうか。 基本的な型については https://github.com/googleapis/googleapis/tree/master/google/type 配下が参考になります。
message Date { int32 year = 1; int32 month = 2; int32 day = 3; }