エンジニアが知るべき、時刻情報を扱う時の落とし穴
「本日なんですが中級エンジニアになるためにはこの経験いるだろうシリーズでそんなシリーズかはいこんなシリーズで今日はですね時刻情報の扱い方を学ぼうという時刻情報の扱い方怖いななんかすごくニッチですどっち系だろうどっち系どっち系設計寄りですね設計寄りはい設計寄りの話ですねあのやっぱり」
「日時情報はやっぱりシステムとは切って離せないものではあってですねやっぱりログとかに日時情報を残したりとかねあとなんかサービスの中で丸々か月以内ならこういうことができるみたいなねそういうものを計算することがあると思うんですけどもめちゃくちゃありますねその辺の設計を見せるとですねめちゃくちゃ泥沼にはまるのでほう」
「正しく設計する正しく日付情報を扱えるそんなエンジニアになってもらいたいじゅんぺんには」
「なんか大事そう大事そうすごい感想ですねっていうぐらいのレベルかもしれないですでも確かに今まで深く考えたことはなかったかもしれないそうなんですね結構気遣った方がいいと思うので今日の話を聞くとですね日付情報を扱う時にこれ気をつければいいんだっていうのが分かるのが一つもう一つが日本に生まれたことを感謝します」
「というので2本立てでいきますね2本立てというか前半後半でね本日種本があってですねソフトウェア設計のトレードオフと誤りという本あれだオレリーのあの」
「人が歩いてるやつだ多分めっちゃありますけどねその中の7章日付と時間のデータを効率よく扱うという章から超抜粋した話をしますめちゃくちゃようやくやっぱこの本ですね海外の本で世界中にユーザーがいるようなサービスの話が書いてあるのであんまり」
「まだ触れたことないな業務でっていう領域もめちゃくちゃいっぱい書いてました絶対ありそうそこまでは話しませんなるほどね詳しく知りたいなら本読んでいただきたいんですけど明日の仕事に生きるなっていうところをお話しさせていただきますできるということでまず予備知識からいきましょう今日の話を進める上で知識を揃えなきゃいけないので怖いな聞かれるよこれ」
「聞かれないかな聞かれないよこれ聞かれないんだ聞かれないよざっくり意識すれば良いのは今日意識すれば良いのは3つ1つ目が時点っていう時に点丸々時点みたいな意味合いの時点これはどういう意味かというととある時間のその瞬間を指すものですね何々時点これはあの」

「その人の場所のローカルタイムとか関係なく宇宙どこにいても同じ時点は存在してますそういう概念的な意味での時点これが一つでもう一つ二つ目エポックエポックあんまり僕聞き慣れなかったんですけど機械学習とかしか聞き慣れないんですけどここでの意味は人工的なゼロ点とある」
「ゼロからどのくらい時間が経ったかっていうのを指すのがエポックっていう話です有名なのはユニックスエポックユニックスタイムはいはいはい」
「こういうのをエポックって言うらしいあんまり見たことないとあるポイントからどれくらい経ったかなるほどねちなみにユニックスタイムは1970年1月1日から1月1日の0か0時00分から何ミリ秒?万秒経ったかを表している数字ですね特にタイムスタンプってやつですよねタイムスタンプってやつですね」
「これ2つ目エポック3つ目タイムゾーンタイムゾーン普段意識しないやつだしないやつかな日本に住んでると時差ないんで国内でタイムゾーンっていうのは時差というか時差があるじゃないですか日本ってグリニッチからUTCからプラス9時間日本の時間ですけど」
「地域地域にタイムゾーンが設定されていてそれぞれ時間がちょっと違うよみたいな感じなんですけどここで意識すべきは自分がいるところの時間とUTCですねUniversalTimeCoordinatedその略なんだねらしいこれは共通協定世界時と呼ばれているもので」
「世界の基準になっている時刻ですねセシウム原子が振動する時間を基準としているらしいんですけどそんなのがあるんですねセシウム時計みたいなやつがあってセシウム時計セシウムの原子が振動する周期が絶対に一定だからこの時計は狂わないっていう理論のやつなんですけどここで注意してほしいのはグリニッチ天文寺とは別です中学校とかの時に世界に」
「本書四五線本書四五線本書四五線がグリニッチ天文台っていうイギリスの天文台通っててそこがなんか時差ゼロですよみたいな話したと思うんですけどしたというか授業受けてると思うんですけどちょっとうっすらなんかフォスタマグナと混ざってます僕フォスタマグナフォスタマグナ新潟と静岡を結ぶやつだろそうそう違う違う違う」
「そこのイギリスの時差ゼロのところもあるんですけどそのグリニッチ天文寺とは別ですUTCはちょっと気をつけてくださいどのくらいずれてるかというとね10分の9秒以内の差がありますね10分の9秒以内0.9秒未満ってことですかそうですね」

「ちょっと違うので基本的にはシステム上の中では標準時刻的にはUTCを使いますのでこちらはお気を付けくださいなるほどね逆にグリニッチはいつ使うんだろうイギリスの人が使うんじゃないですかイギリスのタイムゾーンとして使うんだと思いますっていうので時点とエポックとタイムゾーンこの辺をちょっと意識しながらやっていく必要がありますとで」
「ぶっつけでやってもらって引っかかりつつ都度パスキムの出しながらやっていく感じにいきたいなと思うんですけど体験型なんですね体験型ですね」
「こういうとこ気をつけなきゃいけないんだっていうのを思うためには一度ちょっと引っかかっていただいてから言うのがいいかなと思って聞いていただいている方も一緒に考えていただきたいんですけどECサイトをちょっと思い浮かべて一旦楽天みたいな国内向けのECサイトがいいです海外向けになるとめちゃくちゃややこしくなるんで顧客は3ヶ月以内に返品可能であると」
「いう要件がありますそれをバックエンドエンジニアとして返品可能かどうかを判定する機能を考えてみましょう要するに3ヶ月以内かなって考えていないだわと思ったら返品可能ってする機能を作るってことですねじゃあお願いしますどっから作っていきますかっていうこれ激ムズですよ激ムズですよね」
「もう一回復習していいですかその3つのやつが時点とエポックとタイムゾーンですねエポックあんま関係ないかも時点かタイムゾーンかその瞬間の話かゾーンで見るか僕の前提知識は隅っこぐらいに置いといて普通に機能を作ろうと思った時の思想とかでもいいかもいい気がするな作れって言われたら今どんな気持ちになりますか今なんか」
「ブルーな気持ちですかね仕事嫌いじゃないですか仕事嫌いそうですノリさんもちょっと適宜気づきを促す気の利いた一言を入れながらなるほどね3ヶ月か購入された商品のデータを商品とかその瞬間のいろいろなデータが保存されてると思うんでそこの」
「日付タイムスタンプをまず取ってきます直近3ヶ月以内でしたっけ買ってから3ヶ月以内なら返品できるそこまで言ってません顧客は3ヶ月以内に返品可能であるですじゃあ買ってから3ヶ月以内にしましょうって要件変更しましょうって提案しましょう」
「ノリさんに言ってるんですよOKわかったそれはね素晴らしい気づきですね作戦考えようかじゃあ大丈夫だよ簡単に説得されるんで要件がまず不明確ですねこれはねなんでどの時点から3ヶ月なんですかって話をする必要があります」

「ここで時点が出てきますねなるほどね時点なんていっぱいあるんですよ考えられるとしたらユーザーが購入をクリックしてから3ヶ月かもしれないし購入をクリックした後に決済が成立した後から3ヶ月かもしれないし到着してからの可能性もありますよね到着されてからかもしれないし出荷されてからかもしれないうんうんうん」
「どの時点にしますかそれはPOに決めさせてくれないじゃあ購入してからにしようか勝手にやっちゃいますかそれでこっそりやっちゃおうまず提案していただきありがたいんですけど一旦出荷してからいきましょう出荷してから3ヶ月以内です」
「じゃあきっとその出荷するタイミングのタイムスタンプもきっと保存されてるんですよねされてるはずなのでそれを取ってきますとで出荷されてから3ヶ月だからそっから3ヶ月経った日付を算出するプログラムを書きます3ヶ月って何日?」
「そういうのもあるのか30日か31日かとかもあるのかそうねだからまずそこを決めないといけない気もするねいいですねどうしましょうかじゃあその日が1日だったとしたら1月1日だったら1、2、3」
「3月1日か4月1日3ヶ月を一個一個数えようとしてるよ今3ヶ月間1月1日に出荷されたとしたら4月1日までを3ヶ月間としていいですかどうぞ同じ日3ヶ月後の同じ1月31日だった場合どうする」
「2月28とかそれいけるかそれいけるかそれいけるかなるほど1月31に単純に3を足したら4月31になるけど4月って30までしか数えなかった確かにしかないんで手のボコボコで数えるようになるけど」
「そういう時はちょっとまた相談しますか上司にどうしましょうかそういう人が現れたら相談するそういう人が現れたら1月31だったら僕の考え的には4月31にしたいんですけどないから4月30までにするっていう感じでどうでしょうかって提案をしたいですなるほどいいですかいいですよ良かった」
「じゃあ解決しましたよねこれは3ヶ月間の定期はじゃあちょっともう一つ意思を投げますね3ヶ月以内だなって判断するじゃないですかその判断するタイミングっていつなんですかねそれは注文履歴ページを開いた時は3ヶ月以内かもしれないけどそのページを見て1時間見た時にそれが過ぎたらどうするんだろうページ開いたらちょっときついんじゃないですかね」

「ページ注文履歴のページを開いたタイミングで1時間経過したからやっぱ3ヶ月過ぎてダメっていうのはきつい実装的にきついってことですかまずそれになると開いた時間を保存しておかなきゃいけないから実装がちょっとめんどくさくなりそうだなっていうのとあと開いたまま1ヶ月経ったら果たしてそれは3ヶ月と言えるのかという極論じゃあ」
「返品しますっていう確定ボタンを押したタイミングを時点3ヶ月の時点とする3ヶ月以内のリミット発送から注文キャンセルのリクエストまでリクエストはいどうですかいいと思いますそれでいきますおさらいすると」
「購入時点じゃないなユーザーは3ヶ月以内って言ってるその3ヶ月のスタートの時点は物が発送されてからその時点発送されたレコードの時点から返品しますのボタンを押す時点までが3ヶ月とちょっと待ってって言ってたよねなんか不安なものがありました?発送される場所とか」
「日本じゃなくてイギリスとかだったら非常にいいところに気づいたんですが今回のテスト範囲外なので一旦国内でいいよめちゃくちゃややこしくなるそれを考えるとその辺がこの本書いてたんですけどねそしたら」
「もう懸念点ないので実装して勝手にリリースします勝手にリリースするんだじゃあ要件とか基本設計の方針とか固まりましたか実装していくわけなんですけどものりさんもじゅんぺんもですけど日時を使う」
「実装するときに気をつけてることとかなんかありますかね気をつけるべきことオープンクエスチョンすぎてあれですけどじゃあ質問します日時は言語なんでもいいんですけどどういう形式にしますかまあなんかあのYYYFMまあ2023その日付まず202309何時ですか1017とかで同じように何時何分何秒」
「もうちょっと後ろプラス4桁ぐらい秒の後もつける感じですね今までそれぐらいですねちょっと僕の質問の仕方が悪かったかどうかを確認するためにのりさんにも聞いていいですかタイムスタンプタイムスタンプそれはどうやって実装するんですかPHPとかだとPHPとかだとはい」
「PHPなのかなこれなんでもいいですよデータベースの型をまずタイムスタンプにしますねはいはいはいPHPで扱うのであればデートオブジェクトを使うかカーボンっていうライブラリを使うかどっちかになると思いますよかった基本的にはライブラリを使いましょうデート型とかPythonで言うとデートタイム型とか色々ありますけどなぜかっていうと」

「他のシステムと連携するときに困り売ります基本的には多分バックエンドってことはデータベースとフロントエンドと情報のやり取りがあるはずそういうデータベースとかフロントエンドってバックエンドと違う言語であったり全く同じ型を扱えない場合があると思うので共通フォーマットでやり取りする必要が」
「あるじゃないですかよくある共通フォーマットってISO8601って言われる時刻情報をこういう形でやってねっていう取り決めがあるんですねで言語に」
「色々あるデイト型とかってISO8601の型に変換しやすい変換する機能とかそこからデイト型に戻す機能とかがついている基本的には自分で実装するんじゃなくてちゃんとライブラリを使ってやりましょうとちょっと弁解させてくださいライブラリ使ってますライブラリ使った上でさらに表示する形式を自分でいじれたりするじゃないですか例えばスラッシュを入れるようにするそういう意味でした」
「どうなんですかねあんまりいじらん方がいいともすら思ってる変換できるなら問題ないけどねもし拡張する必要があるんだったら既存のデート型をオーバーロードオーバーライドオーバーライドして」
「ちょっと抽象化して共通の型として使えるようにしましょうみたいな話は書いてましたねちょっとそこまでやりたいなと思ったことは僕一回もないんですけどSQL系だとそういうタイムスタンプ使ったりとかMongoDBでもデイトタイムそのままデイト型だっけなデイトタイム型だっけなそういうMongoDBのライブラリー」
「クライアントライブラリっていうのかなPythonでいうPyMongoみたいなそれにデイトタイムそのままつっこいばよしなにやってくれるみたいな固まったりするのでそういうのを活用することで効率よく実装できますねとなるほどというのがありますね日付はだいたいどの言語でもライブラリなり組み込みのオブジェクトなりありますからねあるはずですよね実装はそんな感じ気を付けましょうかなんですが次テストですねテスト」
「テストケースですよテストのことを考えるとなちょっと時を戻したくなるわ3ヶ月の定義を90日にしたくなるわいや3ヶ月にしてくださいそこは3ヶ月後という」
「機能の場合どういうテストケース考える必要がありますかねちなみに参考までにAmazonは30日ですね返品ポリシーは効率いいですね気持ちはわかる絶対そっちの方がいいよ90日に確かになるほどここは僕も多分パワーで90日にしちゃうと思いますパワーでうるせえ絶対こっちの方がいいって言うただ今回3ヶ月後なんでね勉強のために」

「さっき言ってたことを意識すればいいわけですよね基本的によしじゃあまず時点を意識してみようはい個別に3ヶ月1月1日発送されたら4月1日までかどうかをやりますっていう一般的なやつを書いてその中でも」
「例えば31日だったけど3ヶ月後が30みたいになっちゃった時はそれでOKとするっていう僕はもう一つあると思ったうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうるうる」
「異常系のテストとかそういう意味合いで正常系の境界値分割テスト的な意味で今の4月1日1月1日から4月1日は多分4月1日は良くて4月2日はダメみたいなテストするんですよねはい1月1日の3ヶ月さっきの1月31日から4月30日も4月30日は良くて5月1日はダメってテストするんですよねもう一個」
「で順平が言ってたルードシなんですけど11月30から2月29あれ?あってるよね?あってるよね?2月29にちゃんとなるかこの辺見ときゃいいんじゃないって思います確かに」
「扱ってるデイト型のライブラリがウルドシ対応してませんだったらダメですからね確かにねしてると思うんですけどねそこチェックしておけば普通に日付が曲げ戻るケース全部テストできるのかだと思いますっていうので最初に投げかけた3ヶ月以内に返品ができるっていうふわっとしたやつ実装できますが」
「この日時が入ってきてなおかつその3ヶ月後っていう人間はなんとなくふわっと理解しちゃうけど厳密に考えると結構ややこしいぞっていうのはまあ体感できたんじゃないかなとこういうところをちょっと気をつけていかないとまず要件というか設計最初の方針時点で今だから3ヶ月後っていうのを受領した時点でややこしいことになってるんで確かに」
「時間の要件を受け取った時にこれめんどくさそうこっちに変えたいですって懇願する力これによってエンジニアとして暇を作れるんじゃないかなと思っております顧客の体験を損なうんだったら無理やりやった方がいいんですけどそこはちょっとうまく判断してほしいなというのが今のが前半の日時情報気をつけるべきこと」
「確かに日数でカウントすべきですね楽だねそれを提案するときの提案力も求められますよね求められるねこれだと実装が複雑になるんでこっちでいいですかって言ったらなんか却下したくなるけどいやこれ明確に90日の方がお客さんも分かりやすいですって言ったらね通りやすいかもしれないしね丸暗記します丸暗記はやめた方がいいかな」

「続いてですね日本に生まれてよかったって話をさせてくださいこの章の話半分くらいこの話だったんですけどタイムゾーンですねタイムゾーンややこしいって話でサマータイムって知ってますか知ってるな1時間くらいでしたっけそうそうそう日本ではないんですけども夏とかにですね日の出時刻が早まる夏とかに時計の針を1時間進めて」
「昼間有効に使おうぜっていう施策なんですけどなので年に1回時計が1時間早くなったり1時間遅くなったりするんですねこれがとんでもなく実装にややこしく影響してくるなとそれやばいよねなんかどっかの国配信したりしましたよね最近そうなんだ」
「それで言うとね日本もめっちゃ昔にやってて1948年から1952年にかけて4年間やってて廃止されたんですけど懐かしい何歳?どういうこと?前世の記憶?懐かしい日本でこれが廃止された理由は日本人はルーティーンというか」
「一定の習慣を好むため廃止されたって書いてましたそうなんだ戦後間もない頃ってこと?普通にアメリカに導入されたのかなそうかもしれないですね例えばなんですけどねアメリカで2時半に毎日バックアップしようとシステムのバックアップしますっていう機能を実装するとサマータイムに入った日は1時59分の次3時になるのでゼロ回になったりとか逆に戻る日は」
「1時59分から1時になるんで普通に1回実行されるとかそういうのに考慮しなきゃいけないとなるほどねきつめんどくさいですよねはたまたサマータイムなくなったりするんでやっぱりクリーンによってはなくなるの想定して実装しなきゃいけなかったりね変わったりするのとかね大変だなにそれとなおかつね一つのクリーンだったらそうですけど」
「さっきじゅんぺいがちょっと触れてた海外事業者の荷物の発送のタイムゾーンどうのとかって言ってそのタイムゾーン発送時点がまさかのサマータイムのどうのとかねであとその丸々3ヶ月後にそのサマータイムの切り替えが重なった時どうするのとかねめんどくさーいめんどくさーいですよ日本でよかったー本当に感謝しましょうサマータイムないし時差もないもんね国内で」
「アメリカとかだったら国内で時差あるもんね国内で時差あるのも結構やばいですよね確かに全員UTCの時計持ってんじゃないの確かに本当にみんな共通の時間使えばいいのになって思うけどね本当ですよねそんなに太陽の雪沈みというか日の出と日の入り大事なんですね確かにっていうのが日時情報めんどくさい話でしたはい」
「本当にこれ以外にもいろいろな著者の苦労話とかがいろいろ書いてて海外大変だなと思った次第でございましたなるほどね確かに日本でよかったかもしれないちなみにその書籍あれじゃないですか設計のトレードオフみたいな感じじゃないですか日付にまつわるトレードオフみたいなやつあるんですかあんまりなかったように思えるな効率よく実装しようみたいなところに終始しててこの章についてはあんまり」

「効率よく扱うっていう章なんでトレードオフっていうのはあんまりなかったかなと思ってます設計の部分にフォーカスされてるんですねこの本はですね僕擦れるなと思ってるので擦れるなと思ってるな相当擦れますこれはすごいです気になる章いっぱいあります穴あけようすりすりしてくるんでここからちょいちょい入れていこうかなと思ってますいいですねアフタートークでちょっと面白い小話1個ピックアップしたんですけど」
「この本から和田さんがツイートしてやったやつなんですけどこの本ではユニットテストと単体テストを明示的に書き分けてますユニットテストと単体テストこの訳し分けあるんだってのを僕知らずほう」
「確かに知らんくない一緒じゃない英語で言われたらどっちもユニットテストになりそうだけどそうそうそうそう全然知りませんどうやらユニットテストはテスト駆動開発の1ステップで動く設計書として書かれたものをユニットテスト単体テストは人力であっても自動であっても独立した1つのモジュールの動作保証を行う品質保証の1ステップっていう」
「TDDだったらユニットテストだしそうじゃない品質保証的なやつだったら単体テストみたいななんか訳し分けがあるらしいですそんな意識して使ったことがない確かにな分けることによって嬉しみあるのかなユニットテストは全部自動化されてる前提ってことだね設計書として書かれてるか品質保証としてやるかなんで自動化されてるっていうのは」
「コードテストってやるねポチポチやる系で仕様書使うやつじゃなくてコーディングでやるユニットテストはテスト駆動開発のワンステップで動く設計書だからテスト駆動開発ってことは自動テストユニットテストテストコードを書きながらソースコードを書いていく開発手法なので自動テストなのは確定している書く順番が違うのは」
「順番が違いますよねユニットテストはユニットテストから書けますよね単体テストはコード書いた後に書くのかな自動化されてるって言うんですねテストコードを書いてそのテストがそのテストコードが通るように実装するって言うんですかねそれがちょっと違う特に言うTDDって言うんですかテスト駆動開発それを」
「自動化されてるって言ったやつね樋口順平は多分自動化のニュアンスが引っかかってるね自動化ねそもそも手でやるのが手動テストねコードで書いてテストするのが自動テスト深井あーなるほど樋口あーそうだね確かに深井自動で動いてるみたいなイメージになっちゃってたんで」
「あれだね多分一般的にはだいたいコードでテストを書くときってCICDに組み込んで自動でテストもあるようにするから割と自動テストって言いがちだよねCICDのよりも前からあります自動テストって言葉なんでも本当にテストコードと呼ぶのが世の中に出る前にテストって言葉があってテストコードを」

「テストできるやん自動だーってなって自動テストだと思いますこれは何のリファレンスもないですけどそうだろうと思ってます書いてるから自動じゃない自動で自動って言うと勝手にコードが生成されてるみたいなイメージだったんですけどそういうことじゃないコード書いたからそれに基づいて自動でテストされるからってことですね解決されましたこういう」
「これはページの下の注釈の情報なんですけどリリットテスト、解体テストみたいなそういう注釈もちょいちょいそうなんだみたいなのがあってね情報量の多い本ですね非常にこれからもちょっといろいろ紹介していくのでおもろそうと思ったらぜひ読んでみてくださいお願いしますありがとうございます」
「終わりますねハッシュタグひまじんプログラマーでSNSのXにてポストを募集してますのでお気軽にフィードバックコメント感想お願いしますギャンギャンお願いしますギャンギャンお願いしますあとは説明欄からGoogleフォームでお手入れ質問要望等を募集してますのでそちらもお願いしますお願いします皆様のお便りを読むかもしれません」
「ちゃんと読んでます読んでおりますね紹介するかはちょっとどうだろうかなんですけどねそれではまた次回バイバイバイ」
「こちら現場ののりさんですなんとかけ出しエンジニアを成長させるポッドキャスト番組ひまじんプログラマーの週末エンジニアリングレッスンの最新話が配信されたようです今回はどんなエピソードなんですかねいやーちょっとわからないんですけど私もちょっと家に帰ったら早速聞いてみたいと思います気になりますねのりさん中継ありがとうございました続いては秋の訪れを感じるこんなニュースが届きました」