Go言語の time.Time
型の比較は比較演算子が使えず、
Time.Before
と Time.After
を使う必要があります。
日本の Gopher あるあるだと思うんですが、これって覚えられないですよね・・・。
英語のネイティブスピーカーだと楽勝なんでしょうか。
よくわからなくって毎回ググっているので、対応表にまとめました。
対応表
大小関係 | Go での記述 | |
---|---|---|
t == u |
⇔ | t.Equal(u) |
t > u |
⇔ | t.After(u) |
t < u |
⇔ | t.Before(u) |
t >= u |
⇔ | !t.Before(u) |
t <= u |
⇔ | !t.After(u) |
以上
2023-10-24追記: Go 1.20 から Time.Compare が追加されました。 これを使うと以下のように書けます。
大小関係 | Go での記述 | |
---|---|---|
t == u |
⇔ | t.Compare(u) == 0 |
t > u |
⇔ | t.Compare(u) > 0 |
t < u |
⇔ | t.Compare(u) < 0 |
t >= u |
⇔ | t.Compare(u) >= 0 |
t <= u |
⇔ | t.Compare(u) <= 0 |
不等号の向きが一緒なので覚えやすいですね!
追記ここまで
確認コード
日時の比較をわかりやすくする Bad Know-How として Time.UnixNano
を使うという手があります。
Unix Timestamp は整数なのでおなじみの比較演算子を使えます。
ただし厳密には Monotonic Clocks があるので、結果がことなる場合があることに注意が必要です
(SEE ALSO: Go1.9 から使える Monotonic Clocks を試してみた)。
あとは Time.UnixNano
の戻り値は 1678 年から 2262 年の間でしか保証されないというのもありますね。
2262 年問題が発生するけど、みんな気にしないんだろうか・・・まあ気にしたところで、そのとき作者は死んでるわけですが。
とはいえ 2038 年問題を埋め込んでしまった人たちも同じことを考えていたはず。
今どき新規コードで 2038 年を埋め込むのはいただけないですが、どれだけの未来を想定すれば十分なんだろう?
ちょっと話がそれました。
こういうコーナーケースがあるので Bad Know-How なんですが、わかってさえいれば簡易チェックには使えます。
表を作ったものの不安でしょうがないので、Time.UnixNano
を使って検証コードを書いてみました。
何も出力されなければ問題なし。ヨシ!
package main
import (
"log"
"time"
)
func main() {
test(func(t, u time.Time) bool {
return t.UnixNano() == u.UnixNano()
}, func(t, u time.Time) bool {
return t.Equal(u)
})
test(func(t, u time.Time) bool {
return t.UnixNano() > u.UnixNano()
}, func(t, u time.Time) bool {
return t.After(u)
})
test(func(t, u time.Time) bool {
return t.UnixNano() < u.UnixNano()
}, func(t, u time.Time) bool {
return t.Before(u)
})
test(func(t, u time.Time) bool {
return t.UnixNano() >= u.UnixNano()
}, func(t, u time.Time) bool {
return !t.Before(u)
})
test(func(t, u time.Time) bool {
return t.UnixNano() <= u.UnixNano()
}, func(t, u time.Time) bool {
return !t.After(u)
})
}
func test(f, g func(t, u time.Time) bool) {
a := time.Now()
b := a.Add(1)
c := a.Add(-1)
if f(a, a) != g(a, a) {
log.Println(a, a)
}
if f(a, b) != g(a, b) {
log.Println(a, b)
}
if f(a, c) != g(a, c) {
log.Println(a, c)
}
}