Golangの時刻関連まとめ

忘れて毎回ググってる気がするので、自分用にまとめ。

go version go1.9.1 darwin/amd64

現在の年、月、日、時、分、秒、ナノ秒を取得する

package main

import (
	"fmt"
	"time"
)

func main() {
	now := time.Now()
	fmt.Println(now.Year())       // 2018
	fmt.Println(now.Month())      // February
	fmt.Println(now.Day())        // 21
	fmt.Println(now.Hour())       // 17
	fmt.Println(now.Minute())     // 24
	fmt.Println(now.Second())     // 23
	fmt.Println(now.Nanosecond()) // 510293774
}

日付オブジェクトを作成する

ナノ秒の指定が必要なので注意。

package main

import (
	"fmt"
	"time"
)

func main() {
	t := time.Date(2018, 2, 1, 12, 34, 56, 0, time.UTC)
	fmt.Println(t) // 2018-02-01 12:34:56 +0000 UTC
}

現在の曜日を取得する

package main

import (
	"fmt"
	"time"
)

func main() {
	now := time.Now()
	fmt.Println(now.Weekday())      // Wednesday
	fmt.Println(now.Weekday() == 3) // true
}

規定のフォーマットで時刻文字列をパースする

RFC等で定義されているフォーマットでパースできる。 対応フォーマットの一覧はこちら

package main

import (
	"fmt"
	"time"
)

func main() {
	rfc3339, _ := time.Parse(time.RFC3339, "2018-02-21T12:34:56Z")
	fmt.Println(rfc3339) // 2018-02-21 12:34:56 +0000 UTC
}

任意のフォーマットで時刻文字列をパースする

package main

import (
	"fmt"
	"time"
)

func main() {
	layout := "2006年1月2日 15時04分05秒"

	now := time.Now()
	fmt.Println(now.Format(layout)) // 2018年2月21日 23時28分07秒
}

Unixtimeを取得する

package main

import (
	"fmt"
	"time"
)

func main() {
	now := time.Now()
	fmt.Println(now.Unix())     // 1519223320
	fmt.Println(now.UnixNano()) // 1519223320054801608
}

Unixtimeを時刻オブジェクトに変換する

package main

import (
	"fmt"
	"time"
)

func main() {
	unixtime := time.Now().Unix()
	fmt.Println(time.Unix(unixtime, 0)) // 2018-02-21 23:29:05 +0900 JST
}

時刻を比較する

package main

import (
	"fmt"
	"time"
)

func main() {
	now := time.Now()
	yesterday := now.AddDate(0, 0, -1)
	tomorrow := now.AddDate(0, 0, 1)

	fmt.Println(now.Equal(now))        // true
	fmt.Println(now.Before(yesterday)) // false
	fmt.Println(now.Before(tomorrow))  // true
	fmt.Println(now.After(yesterday))  // true
	fmt.Println(now.After(tomorrow))   // false
}

時刻の差分を求める

package main

import (
	"fmt"
	"time"
)

func main() {
	t1 := time.Date(2018, 2, 1, 0, 0, 0, 0, time.Local)
	t2 := time.Date(2018, 2, 12, 3, 4, 56, 0, time.Local)

	duration := t2.Sub(t1)
	fmt.Println(duration)               // 267h4m56s
	fmt.Println(duration.String())      // 267h4m56s
	fmt.Println(duration.Hours())       // 267.08222222222224
	fmt.Println(duration.Minutes())     // 16024.933333333332
	fmt.Println(duration.Seconds())     // 961496
	fmt.Println(duration.Nanoseconds()) // 961496000000000
}

時刻を加減算する

日以上の単位を扱う場合はAddDate、時以下の単位を扱う場合はAddを使用する。 減算する場合は負の値をAddすれば良い。

package main

import (
	"fmt"
	"time"
)

func main() {
	t := time.Date(2018, 2, 1, 0, 0, 0, 0, time.Local)

	fmt.Println(t.AddDate(1, 0, 0))  // 2019-02-01 00:00:00 +0900 JST
	fmt.Println(t.AddDate(-1, 0, 0)) // 2017-02-01 00:00:00 +0900 JST

	fmt.Println(t.AddDate(0, 1, 0))  // 2018-03-01 00:00:00 +0900 JST
	fmt.Println(t.AddDate(0, -1, 0)) // 2018-01-01 00:00:00 +0900 JST

	fmt.Println(t.AddDate(0, 0, 1))  // 2018-02-02 00:00:00 +0900 JST
	fmt.Println(t.AddDate(0, 0, -1)) // 2018-01-31 00:00:00 +0900 JST

	fmt.Println(t.Add(10 * time.Hour))  // 2018-02-01 10:00:00 +0900 JST
	fmt.Println(t.Add(-10 * time.Hour)) // 2018-01-31 14:00:00 +0900 JST

	fmt.Println(t.Add(10 * time.Minute))  // 2018-02-01 00:10:00 +0900 JST
	fmt.Println(t.Add(-10 * time.Minute)) // 2018-01-31 23:50:00 +0900 JST

	fmt.Println(t.Add(10 * time.Second))  // 2018-02-01 00:00:10 +0900 JST
	fmt.Println(t.Add(-10 * time.Second)) // 2018-01-31 23:59:50 +0900 JST
}

元日からの経過日数を取得する

元日は1なので注意。

package main

import (
	"fmt"
	"time"
)

func main() {
	ganjitsu := time.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC)
	fmt.Println(ganjitsu.YearDay()) // 1

	now := time.Now()
	fmt.Println(now.YearDay()) // 52
}

一定周期で処理を行う

time.Tickerを使う。

package main

import (
	"fmt"
	"time"
)

func main() {
	ticker := time.NewTicker(2 * time.Second)
	for {
		select {
		case <-ticker.C:
			fmt.Println(time.Now(), "2秒おきに実行されます")
		}
	}
}

実行結果

2018-02-21 23:16:26.237385932 +0900 JST m=+2.001250465 2秒おきに実行されます
2018-02-21 23:16:28.238423022 +0900 JST m=+4.002294555 2秒おきに実行されます
2018-02-21 23:16:30.240657426 +0900 JST m=+6.004535959 2秒おきに実行されます
2018-02-21 23:16:32.238256942 +0900 JST m=+8.002143475 2秒おきに実行されます

一定時間経過したら通知する

selectでタイムアウトさせたい場合は、time.Afterを使う。

package main

import (
	"fmt"
	"time"
)

func main() {
	dummy := make(chan struct{})
	fmt.Println("開始", time.Now())
	for {
		select {
		case <-dummy:
			// do something
		case <-time.After(2 * time.Second):
			fmt.Println("終了", time.Now())
			return
		}
	}
}

実行結果

開始 2018-02-21 23:23:47.961820215 +0900 JST m=+0.000425594
終了 2018-02-21 23:23:49.965069407 +0900 JST m=+2.003681786