API越しでタイムスタンプをやりとりする時のフォーマットをどうするべきか
APIのリクエストにせよレスポンスにせよ、タイムスタンプを利用するというのはよくある話です。
この時、そのタイムスタンプのフォーマットをどうするのが良いのかという話題です。IDLを使って縛るというというのは良い考えだと思いますが、IDLを使うにせよフォーマットについては決めなくてはならないので。
1. 文字列を使う
これあんま良くないと思うんですよね……というのも、とあるAPIを触っている時に「タイムスタンプはRFC3339です」というフィールドがあったんですけれどRFC3339ではないフォーマットで返却されたり受け入れられたりしたのであまり信用ができない……
まあフォーマットが不正というのは極端な例かもしれないですが、仮にフォーマットが不正だと多くの場合 strptime()
や time.Parse()
なんかの時刻文字列のparserが正しく動かず (良いケースだとエラーが上がる、悪いケースだと本来意図しない時刻として扱われる。後者が大きな問題) システムが壊れると思うのでunix timeを使ったほうが良いと考えています。あといまだにstrptime/strftimeの変換指定が満足に覚えられない!
あとタイムスタンプ文字列だと無邪気にタイムゾーン情報が欠落してたりすることがあるんで、それもunix timeを使ったほうが良いと考える一因です。まあちゃんとタイムゾーン情報を付けてくれれば良いんですけど。
グローバル社会になって久しい一方で無邪気にタイムゾーンを省いたタイムスタンプ文字列がAPI越しに飛んできて俺の頭は爆発寸前だ……
— moznion (@moznion) 2021年12月9日
2. unix timeを使う
まあこれが穏当なんじゃないですかね、UTCであることも明確だし……と思いきやこういった落し穴が。
精度は秒の整数か、millisec単位の整数(秒の1000倍)か、subsecが入った浮動小数点のどちらがよろしいでしょうか…
— fujiwara (@fujiwara) 2021年12月9日
これについては2つあると思っていて、時間の解像度 (単位) についてはフィールドに _sec
とか _ms
のような接尾辞を付けることで明確にするように心がけています。本質的にミスを防げるかというと怪しいですが、無いよりは良いでしょう、という考えです。
unixtime返したり受けたりするAPI、最近はパラメータ名に単位付けるように心掛けています。`received_time_epoch_sec` とか `created_time_epoch_ms` とか……冗長だけど。
— moznion (@moznion) 2021年12月9日
もう一つの「整数か小数か」については型として縛るというのが方法じゃないでしょうか……IDLでやるのが良いのでしょうね。
3. TAI64を使う
https://cr.yp.to/libtai/tai64.html
やった、一意なフォーマットだ!!!
とはいえ人間が基本的には読めない、うるう秒の扱いが特殊、など色々ありこれはこれで困りそうですね。
やっぱtai64nしか救いはないな、djbを信じろ
— moznion (@moznion) 2021年12月9日
果たしてそうだろうか?
現時点での個人的な見解
- unix timeを使う
- 分解能は何らかの方法で明示する
- IDLを使う
というあたりが現実的な落しどころじゃないでしょうか。他になにか、APIのリクエスト・レスポンスに使えそうな先鋭的な時間表現ってあるんでしょうか?
[追記]
unix timeだと結局タイムゾーンを別途送るべきって話になりません?
— FUJI Goro (@__gfx__) 2022年1月11日
つまり、あるアクションが行われたとき、それがローカルタイムの朝なのか夜なのかはマーケ的には重要な情報だったりするわけで。
それって、そのAPIをcallしたユーザーの属性情報 (どこに住んでいるか) で突き合わせることができませんかね? あるいはGEO IPとか……いちいちTZ情報含んで送ってきてもらうのは大変な感じが。
— moznion (@moznion) 2022年1月11日
分析チームが「ノイズがあってもよい」というのに了承してくれるのであればそれでいいんじゃないですか。
— FUJI Goro (@__gfx__) 2022年1月11日
ただしノイズが含まれている確率は不明ですが…。
APIの特性に依ると思っていて、TZが必要なものであれば付ける、というのは同意です。ブラウザを使っているようなものだったらTZ取るのも難しくないでしょうし。
— moznion (@moznion) 2022年1月11日
一方でそういうのが必要ないAPIもあると思っていて、僕がよく扱うのはそういうAPIだったという話だと思います。
それは全くそのとおりです。一方でログは取り直しできないので、「時間には思考停止でtimezone情報はつけておけ」とも思います。
— FUJI Goro (@__gfx__) 2022年1月11日
プロトコルバッファーっていう大統一シリアライゼーションフォーマットに身を任せて、公式に出しているTimestampかタイムゾーンが必要ならCivil Timestampを使うってやつもありますね…… https://t.co/V6ylWGxffS
— ネコへの態度を悔い改めよ (@draftcode) 2022年1月11日
ちなみにUNIX timeでdoubleの型をつけておけば「あ、これは"UNIX time"は定義上sec単位であるという派閥に乗っ取りつつ、それより細かい精度は小数で示せということなんだな」ということを人類の忖度能力を持ってすれば察せないですかね。
— ネコへの態度を悔い改めよ (@draftcode) 2022年1月11日
[追記ここまで]