Goの時刻系の覚書

2022/02/06に公開

現在時刻

now := time.Now()

ロケーション生成

gmt, _ := time.LoadLocation("GMT")

指定時刻の生成

target := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, gmt)

計算

// 年月日系は以下
yesterday := time.Now().AddDate(0, 0, -1)
last_month := time.Now().AddDate(0, -1, 0)
next_year := time.Now().AddDate(1, 0, 0)
// 時分秒系は以下
thirty_minutes_later := time.Now().Add(time.Minute * 30)
fourty_hours_ago := time.Now().Add(time.Hour * -40)

30分後のきっかりの時間

多分上記の組み合わせ。泥臭い。

later30 := now.Add(time.Minute * 30)
target := time.Date(later30.Year(), later30.Month(), later30.Day(), later30.Hour(), later30.Minute(), 0, 0, later30.Location())

文字列から時刻への変換

よくあるYMD形式によるパースではなく、独特(というかなかなか覚えられない)。

s := "Tue, 01 Feb 2022 06:43:56 GMT"
layout := "Mon, 02 Jan 2006 15:04:05 MST"
modified_date, err := time.Parse(layout, s)

謎のフォーマットの根拠はこの辺りを参照。
01/02 03:04:05PM '06 -0700

項目 指定すべきもの バリエーション例
2006 2006,06
1 Jan,January
2 2,02
Mon Mon,Monday
15 15
4 4,04
5 5,05
TZ MST MST, -0700

或いは、文字列のフォーマットが野良フォーマットではなく何らかの基準に準拠しているのであれば、
timeに用意されているconstを利用するのが楽。(下表はconstから抜粋)

s := "Tue, 01 Feb 2022 06:43:56 GMT"
modified_date, err := time.Parse(time.RFC1123, s)
定数名 レイアウト
ANSIC Mon Jan _2 15:04:05 2006
UnixDate Mon Jan _2 15:04:05 MST 2006
RubyDate Mon Jan 02 15:04:05 -0700 2006
RFC822 02 Jan 06 15:04 MST
RFC822Z 02 Jan 06 15:04 -0700
RFC850 Monday, 02-Jan-06 15:04:05 MST
RFC1123 Mon, 02 Jan 2006 15:04:05 MST
RFC1123Z Mon, 02 Jan 2006 15:04:05 -0700
RFC3339 2006-01-02T15:04:05Z07:00
RFC3339Nano 2006-01-02T15:04:05.999999999Z07:00

時刻の比較

gmt, _ := time.LoadLocation("GMT")
d1 := time.Date(2022, 2, 2, 22, 22, 22, 0, gmt)
d2 := time.Date(2022, 2, 2, 22, 22, 23, 0, gmt)
d3 := time.Date(2022, 2, 2, 22, 22, 24, 0, gmt)

fmt.Println(d1.Before(d2)) // true
fmt.Println(d2.Before(d2)) // false
fmt.Println(d2.Equal(d2)) // true
fmt.Println(d2.After(d2)) // false
fmt.Println(d3.After(d2)) // true

a.Before(b) -> aはbより過去
a.Equal(b) -> aとbは同じ
a.After(b) -> aはbより未来

Discussion