時間の取り扱いは非常に複雑です。時間に関する一般的な誤った考えは以下のものがあります。
- 1日は24時間で構成されているということ。
- 1時間は60分を含んでいるということ。
- 1週間は7日で構成されているということ。
- 1年は365日で構成されているということ。
例えば、1 は特定の時点に24時間を追加しても常に新しいカレンダー日が得られるとは限らないことを示しています。
したがって、時間を取り扱う際は常に"time"
パッケージを使用し、これらの誤った考えをより安全かつ正確に取り扱うのに役立ちます。
time.Time
を使用して瞬時の時間を表現する
瞬時の時間を扱う際は、time.Time
とそのメソッドを使用して時間の比較、加算、減算を行います。
お勧めしない方法:
func isActive(now, start, stop int) bool {
return start <= now && now < stop
}
推奨される方法:
func isActive(now, start, stop time.Time) bool {
return (start.Before(now) || start.Equal(now)) && now.Before(stop)
}
time.Duration
を使用して時間の長さを表現する
時間の長さを扱う際は、time.Duration
を使用します。
お勧めしない方法:
func poll(delay int) {
for {
// ...
time.Sleep(time.Duration(delay) * time.Millisecond)
}
}
poll(10) // 秒またはミリ秒でしょうか?
推奨される方法:
func poll(delay time.Duration) {
for {
// ...
time.Sleep(delay)
}
}
poll(10*time.Second)
最初の例に戻り、瞬時の時間に24時間を追加する際は、使用するメソッドは意図に依存します。現在の日の翌日に同じ時間点を取得したい場合は、Time.AddDate
を使用する必要があります。しかし、前回の時間よりも24時間後であることを確認したい場合は、Time.Add
を使用する必要があります。
newDay := t.AddDate(0 /* years */, 0 /* months */, 1 /* days */)
maybeNewDay := t.Add(24 * time.Hour)
time.Time
およびtime.Duration
の外部システムとの使用
外部システムとのやり取りにおいては、可能な限りtime.Duration
およびtime.Time
を使用してください。例えば以下のような場合です:
- コマンドラインフラグ:
flag
はtime.ParseDuration
を通じてtime.Duration
をサポートします。 - JSON:
encoding/json
はUnmarshalJSON
メソッドを使用し、time.Time
をRFC 3339形式の文字列にエンコードします。 - SQL:
database/sql
はDATETIME
またはTIMESTAMP
列をtime.Time
に変換し、基礎となるドライバーがサポートしている場合に返します。 - YAML:
gopkg.in/yaml.v2
はRFC 3339形式の文字列としてtime.Time
、またはtime.ParseDuration
をサポートします。
これらのやり取りにおいてtime.Duration
を使用できない場合は、int
またはfloat64
を使用し、フィールド名に単位を含めます。
例えば、encoding/json
はtime.Duration
をサポートしていないため、フィールド名に単位を含めます。
非推奨:
// {"interval": 2}
type Config struct {
Interval int `json:"interval"`
}
推奨:
// {"intervalMillis": 2000}
type Config struct {
IntervalMillis int `json:"intervalMillis"`
}
これらのやり取りにおいてtime.Time
を使用できない場合は、別途合意がない限り、string
を使用し、タイムスタンプをRFC 3339形式に従ってフォーマットします。デフォルトでTime.UnmarshalText
はこの形式を使用し、time.RFC3339
経由でTime.Format
およびtime.Parse
に使用できます。
実用上の問題ではありませんが、"time"
パッケージは閏秒タイムスタンプの解析をサポートしておらず(8728)、計算において閏秒を考慮していません(15190)。2つの時間の差を比較する場合、その間で発生した閏秒は含まれませんのでご注意ください。