この記事は、Go 言語 Advent Calendar 2023 の21日目の記事です。
Go言語で時間を扱う際の実装のTipsを2つ紹介します。これらは筆者の個人的な経験に基づくものであり、必ずしもすべてのケースに当てはまるわけではありません。
それでは、本題に入っていきましょう
Tips1 引数名
time.Time 型の値を引数として受け取る関数を作成する際の引数名について考えます。
func funcA(now time.Time){
return
}
関数の呼び出しを考えると、以下のように処理が始まるタイミングでtime.Time
型の変数を初期化、funcA
に渡すと思います。
now := time.Now()
funcA(now)
now
という引数名にも違和感がないですね
その際に1点考えて欲しいことが「funcA
が受け取るtime.Time
は、必ずしも現在時刻を期待するのか? 」ということです。
現在時刻を渡すような使用しかしていない場合でも、funcA
の処理自体は現在時刻をマストとして期待していない(指定された日時をもとに処理を実行するだけ)という意味合いであれば、引数名はnow
ではなく、t
が適切なのかもしれません。
Tips2 タイムゾーン
アプリケーションでの時間比較処理におけるタイムゾーンの扱いについて考察します。
時間比較処理には以下のようなシーンが考えられます。
- アプリケーションコードにハードコーディングされている日時との比較
- DBから取得したレコードの時刻型との比較
- などなど
時間比較処理において、time.Time と string を変換する際、time.Time はタイムゾーンを自動的に扱いますが、string への変換ではタイムゾーン情報が失われてしまうことです。
つまりtime.Time
同士で比較をする場合、タイムゾーンは開発者が意識しなくてもうまく変換してくれます。
しかし、time.Time
とString
の変換を介している場合、タイムゾーン情報は保持されません。
例えば、日付をプレフィックスとして持つID(例:2023-12-01-Xxxxx)を現在時刻と比較するシーンがあります。
(マスターデータのIDにプレフィックスとして日付を持たせるケースはよく目にします)
そんなときにcloud.google.com/go/civilパッケージが有用です。提供される時間型(civil.Date
や civil.Time
)はタイムゾーン情報を持たないため、日付のみを扱う場合の比較が容易になります。
そのため、例に挙げたようなマスターデータのプレフィックスを時刻型としてパースする場合は、civil.Date
に変換し、変換対象のtime.Time
型の値もcivil.Date
に変換し、比較することができます。
しかし以下の点に注意する必要があります
- time から civil への変換時にどのタイムゾーンを使用するか
- string で持たせる日時データがどのタイムゾーンを前提としているか
これらのルールをプロジェクト内で定めることで、時間比較を正確に行うことが可能になります。