at backyard

Color my life with the chaos of trouble.

Node.js + Protocol Bufferで時刻を扱う場合に利用するgoogle.protobuf.Timestampについて

自分向けの割合がだいぶ高い備忘録。

gRPCを扱う際に時刻を利用する場合、protocol bufferでは時刻を表す型として google.protobuf.Timestamp が利用できる。
これが個人的にはちょっと癖のある感じで、今のところは使いづらい。

ひとまず概要についてはGitHubのここのソースコメントなどを読んで、なんとなく掴んだ。

github.com

JavaScript(Node.js)からgoogle.protobuf.Timestampを利用する

で、.proto ファイルなどで実際に定義してこのTimestamp型を使う場合だが .proto ファイル上で下記のようにTimestampの利用を明示していれば、実際の処理の中でも使える。
(明示していなくても使えるかは未検証だが、どうだろうか)

import "google/protobuf/timestamp.proto";
・
・
・
message Foo {
  google.protobuf.Timestamp time = 1;
}
・
・
・

google.protobuf.Timestampを用いたサーバ側の処理

実際の処理の中では下記のようにして fromDate 関数を通じてセットできる。

最初、下記のstack overflowを参考にして下記のように書いた。

stackoverflow.com

これでエラーなく動いたが、これだと格納される値が undefined となっていて機能しなかった。

const date = new proto.google.protobuf.Timestamp();
response.setTime(date.fromDate(new Date()));

// ちなみに下記の定義でも動いたが、これは実装しているコードによるのかもしれない?
// const date = new proto.Timestamp();

そこで実際に Timestamp 内の実装を見て試行錯誤しつつ、最終的には下記のようなコードとなった。

const date = proto.google.protobuf.Timestamp.fromDate(new Date());
response.setTime(date);

これでgRPCを用いて時刻のやり取りができる。

google.protobuf.Timestampを用いたクライアント側の処理

受け取った側でもTimestampをJavaScriptで表示するために一手間挟む必要がある。

const time = new proto.google.protobuf.Timestamp(response.getTime().array);
console.log(time.toDate().toISOString());

これで良いのかは定かではない。とりあえず実際のコードを見て調べてみたところ、これに落ち着いたというのが正直なところである。
response.getTime().array という形でTimestampのインスタンスを生成するのは気持ち悪いので、これは想定されたやり方とは異なるのかもしれない。 もしご存じの方がいましたら、コメントいただけると幸いです。

なお、表示するときは time.toDate() だけでも問題はない。ISO形式の文字列で表示したかったので、toISOString() を使っている。

developer.mozilla.org

なお、Protocol Bufferで時刻を扱うことについては、日本語の下記の記事が実装方針を考える上でも参考になりそうだったので、最後に貼らせていただく。

kiririmode.hatenablog.jp