2018年1月9日火曜日

Protocol Buffers のIDL記述(日付型)

Protocol Buffers で定義されているスカラー型の中には日付を意味する型がありませんが、Google の GitHub リポジトリには Timestamp 型があります。この proto ファイルをインポートすれば、C# の DateTime 型を Google.ProtoBuf の Timestamp 型にマッピングさせることができます。

google/protobuf (GitHubリポジトリ)


まず、GitHub リポジトリから proto ファイルをクローンまたはダウンロードしておきます。

対象の proto ファイルに timestamp.proto をインポートし、google.protobuf.Timestamp 型を指定します。

[ Person.proto ]
syntax = "proto3";

import "timestamp.proto";

option csharp_namespace = "Exsample.Models";

message Person {
    string Code = 1;
    string Name = 2;
    google.protobuf.Timestamp Birthday = 3;
}


この proto ファイルからソースコードを生成します。
protoc のコマンドライン引数のインポートディレクトリに timestamp.proto が格納されているディレクトリを指定します。 開発プロジェクトの proto ファイル格納ディレクトリに timestamp.proto をコピーしてもよいのですが、共有ディレクトリで集中管理したいところです。

protoc に対して複数のインポートディレクトリを指定するには、; で連結します。
protoc のヘルプによると、複数のインポートディレクトリが指定された場合は指定された順番でファイルの探索が行われるようです。

[ RunProtoc.bat ]
set PROJECT_DIR={開発プロジェクトの proto ファイル格納ディレクトリ}
set PROTBUF_DIR={google/protobufの proto ファイル格納ディレクトリ}

set IMPORT_DIR=%PROJECT_DIR%;%PROTBUF_DIR%

protoc Person.proto --proto_path %IMPORT_DIR% …


生成された C# ソースファイルには、Google.Protobuf.WellKnownTypes.Timestamp 型の Birthday プロパティが定義されます。この型には .NET Framework の DateTime 型との変換メソッドが定義されています。注意しなくてはならないのが、Timestamp 型には UTC 時刻で渡す必要があるということです。ローカル時刻のままで渡すと例外が発生します。何かしらの仕組みやルールを検討しておいたほうがよさそうです。

// DateTime ⇒ Timestamp
var stamp = Timestamp.FromDateTime(DateTime.Now.ToUniversalTime());

// Timestamp ⇒ DateTime
var date = stamp.ToDateTime().ToLocalTime();



0 件のコメント:

コメントを投稿

paiza のスキルチェックをやってみました

いまさら感はありますが、 paiza のスキルチェックをやってみました。指定された時間内にコードを書いてユニットテストにかけ、その結果を基に評価を数値化してくれるというものですが、ゲーム感覚で空き時間を見つけて進めていこうと考えています。 どうやら時間が短いほど高い評価を得...