Goのtimeパッケージチートシート

## はじめに
以下は `2020年6月`に実行した結果です。
go1.14.3を使用しています


## 現在時刻を取得

```golang:ʕ◔ϖ◔ʔ 
package main

import (
	"fmt"
	"time"
)

func main() {

	// tはtime.Time型
	t := time.Now()
	fmt.Println(t) // 2020-06-01 19:29:04.82858 +0900 JST m=+0.000333352

	t = time.Date(2020, 6, 1, 17, 44, 13, 0, time.Local)
	fmt.Println(t)              // 2020-06-01 17:44:13 +0900 JST
	fmt.Println(t.Year())       // 2020
	fmt.Println(t.YearDay())    // 153 通算日(1~366)
	fmt.Println(t.Month())      // June
	fmt.Println(t.Weekday())    // Monday
	fmt.Println(t.Day())        // 1
	fmt.Println(t.Hour())       // 17
	fmt.Println(t.Minute())     // 44
	fmt.Println(t.Second())     // 13
	fmt.Println(t.Nanosecond()) // 0
	fmt.Println(t.Zone())       // JST 32400
}

```

https://wandbox.org/permlink/jt4vM8ISVkRfYe61

## 月・曜日

```golang:Go
package main

import (
	"fmt"
	"time"
)

func main() {

	t := time.Now()

	// 月は1からの連番
	if time.January == 1 {

		/*
		 * ※　time.goパッケージにて定数を定義しているが、String()を実装している為、Printlnの出力は数値ではない
		 */
		fmt.Println(time.January)  // January
		fmt.Println(time.December) // December
	}

	// 曜日は日曜日から0スタートの連番
	if time.Sunday == 0 {
		fmt.Println(time.Sunday)   // Sunday
		fmt.Println(time.Saturday) // Saturday
	}

	// 日本語化
	weekDays := [...]string{"日", "月", "火", "水", "木", "金", "土"}
	fmt.Println(weekDays[t.Weekday()]) // 月
}
```
https://wandbox.org/permlink/1FcbdEXpOxgrxTSL



## 文字列をパースしてtime.Time型を生成

`func ParseDuration(s string) (Duration, error)`

```golang:Go
package main

import (
	"fmt"
	"time"
)

func main() {
	t, _ := time.ParseDuration("1h30m")
	fmt.Println(t.Minutes()) // 90
}

```
https://wandbox.org/permlink/R9HvHNQuoWd7h6pK


## 時刻の加算


`func (t Time) Add(d Duration) Time`

```golang:Go
package main

import (
	"fmt"
	"time"
)

func main() {

	t := time.Date(2020, 12, 31, 23, 59, 59, 0, time.Local)
	fmt.Println(t) // 2020-12-31 23:59:59 +0900 JST

	t = t.Add(1 * time.Second)
	fmt.Println(t) // 2021-01-01 00:00:00 +0900 JST
}
```
https://wandbox.org/permlink/ISVB3BuzYzBQRj3o




## 時刻の差分

```golang:Go
package main

import (
	"fmt"
	"time"
)

func main() {

	// 2020年末
	yearEnd := time.Date(2020, 12, 31, 23, 59, 59, 999999999, time.Local)
	
	// 6月1日
	now := time.Date(2020, 6, 1, 0, 0, 0, 0, time.Local)
	
	diff := yearEnd.Sub(now)
	fmt.Println(diff) // 5135h59m59.999999999s

	// time.Sinceはtime.Now().Sub(t)のラッパー
	diff = time.Since(yearEnd)
	fmt.Println(diff) // -5135h59m59.999999999s

	diff *= -1
	fmt.Println(diff) // 5135h59m59.999999999s
}

```

https://wandbox.org/permlink/inHPxPrniX3Jvv3C

## 年月日の加算・減算

```golang:Go
package main

import (
	"fmt"
	"time"
)

func main() {
	t := time.Date(2019, 12, 31, 23, 59, 59, 999999999, time.Local)
    
    // 加算
    t1 := t.AddDate(0, 0, 1) // AddDate(y,m,d)
	fmt.Println(t1)         // 2020-01-01 23:59:59.999999999 +0900 JST
    
    // 減算
	t2 := t.AddDate(0, 0, -1) // AddDate(y,m,d)
	fmt.Println(t2)         // 2019-12-30 23:59:59.999999999 +0900 JST}
}
```
https://wandbox.org/permlink/gv3FvrMF7Isalc8j

## 月末を取得

※`2020年6月`に実行した結果です

```golang:Go
package main

import (
	"fmt"
	"time"
)

func main() {
	y := time.Now().Year()  // type int
	m := time.Now().Month() // type Month

	t := time.Date(y, m, 1, 23, 59, 59, 999999999, time.Local).AddDate(0, 1, -1)

	fmt.Println(t) // 2020-06-30 23:59:59.999999999 +0900 JST
}
```

https://wandbox.org/permlink/1vsqI43For9DnDXd


## 時刻の比較

```golang:Go
package main

import (
	"fmt"
	"time"
)

func main() {
	Jan := time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local)
	Feb := time.Date(2020, 2, 1, 0, 0, 0, 0, time.Local)
	fmt.Println(Jan.Before(Feb)) // true  (1月は2月よりも前か?)
	fmt.Println(Jan.After(Feb))  // false (1月は2月よりも後か?)
}
```
https://wandbox.org/permlink/TYFLQNB4iMqJSgzQ

`Before` AはBよりも前か？
`After` AはBよりも後か？
と覚えとくと間違えない

## 期間内か

```go:go
package main

import (
	"fmt"
	"time"
)

func main() {

	// 判定方法その１
	{
		first := time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)
		now := time.Date(2020, 6, 1, 0, 0, 0, 0, time.UTC)
		end := time.Date(2020, 12, 31, 23, 59, 59, 999999999, time.UTC)

		if (first.Equal(now) || first.Before(now)) && (end.Equal(now) || end.After(now)) {
			fmt.Println("期間内")
		} else {
			fmt.Println("期間外")
		}
	}

	// 判定方法その２
	// 開始と終了をずらす
	{
		first := time.Date(2019, 12, 31, 23, 59, 59, 999999999, time.UTC)
		now := time.Date(2020, 6, 1, 0, 0, 0, 0, time.UTC)
		end := time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC)

		if first.Before(now) && end.After(now) {
			fmt.Println("期間内")
		} else {
			fmt.Println("期間外")
		}
	}
}

```
https://wandbox.org/permlink/q3QpRR83Rh8ylN4a

if文の条件が複雑なので、関数を定義するか構造体のメソッドにすると良い

```go:go
package main

import (
	"fmt"
	"time"
)

type Term struct {
	BeginAt time.Time
	EndAt   time.Time
}

func (term Term) Within(t time.Time) bool {

	if term.BeginAt.Equal(t) {
		return true
	}

	if term.EndAt.Equal(t) {
		return true
	}

	if term.BeginAt.After(t) {
		return false
	}

	if term.EndAt.Before(t) {
		return false
	}

	return true
}

func main() {

	now := time.Date(2020, 6, 1, 0, 0, 0, 0, time.UTC)

	t := Term{
		BeginAt: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC),
		EndAt:   time.Date(2020, 12, 31, 23, 59, 59, 999999999, time.UTC),
	}
	if t.Within(now) {
		fmt.Println("期間内")
	} else {
		fmt.Println("期間外")
	}
}

```
https://wandbox.org/permlink/k3STMn9v96tRoxHW

## 文字列から時刻を生成

layoutとvalue（時刻）を指定する
layoutがなぜこのフォーマットなのかは[こちら](https://qiita.com/ruiu/items/5936b4c3bd6eb487c182)を参照

`func Parse(layout, value string) (Time, error)`

```golang:Go
package main

import (
	"fmt"
	"time"
)

func main() {
	t := time.Time{}
	layout := "2006/01/02"
	value := "2020/06/01"
	t, _ = time.Parse(layout, value)
	fmt.Println(t) // 2020-06-01 00:00:00 +0000 UTC

	layout = "2006年01月02日 15時04分05秒"
	value = "2020年06月01日 11時32分40秒"
	t, _ = time.Parse(layout, value)

	fmt.Println(t)         // 2018-03-03 20:01:30 +0000 UTC
	fmt.Println(t.Local()) // 2018-03-04 05:01:30 +0900 JST
}
```

https://wandbox.org/permlink/QikoFpToDAx8u8dt

## 時刻から文字列を生成

```golang:Go
package main

import (
	"fmt"
	"time"
)

func main() {
	t := time.Now()
	fmt.Println(t)                                 // 2020-06-01 20:10:25.857202105 +0900 JST m=+0.000093900
	fmt.Println(t.Format(time.RFC822))             // 01 Jun 20 20:10 JST
	fmt.Println(t.Format(time.RFC3339Nano))        // 2020-06-01T20:10:25.857202105+09:00
	fmt.Println(t.Format("2006/01/02"))            // 2020/06/01
	fmt.Println(t.Format("2006年01月02日 15時04分05秒")) // 2020年06月01日 20時10分25秒
}
```

その他フォーマット https://golang.org/pkg/time/#pkg-constants

```go:go
const (
	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" // RFC822 with numeric zone
	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" // RFC1123 with numeric zone
	RFC3339     = "2006-01-02T15:04:05Z07:00"
	RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
	Kitchen     = "3:04PM"
	// Handy time stamps.
	Stamp      = "Jan _2 15:04:05"
	StampMilli = "Jan _2 15:04:05.000"
	StampMicro = "Jan _2 15:04:05.000000"
	StampNano  = "Jan _2 15:04:05.000000000"
)
```




## Unix時刻との相互変換

```golang:Go
package main

import (
	"fmt"
	"time"
)

func main() {
	t := time.Now()
	fmt.Println(t.Unix())      // 1591096873
	fmt.Println(t.UnixNano())  // 1591096873618624554

	// UNIXからtime.Timeに変換
	t = time.Unix(t.Unix(), 0)
	fmt.Println(t)             // 2020-06-01 20:07:47 +0900 JST
}
```
https://wandbox.org/permlink/5IHEZbvhJ8a7ZGdU

## タイムゾーンの指定

```golang:go
package main

import (
	"fmt"
	"time"
)

func main() {
	t1 := time.Date(2020, 6, 1, 0, 0, 0, 0, time.UTC)
	fmt.Println(t1)

	t2 := time.Date(2020, 6, 1, 0, 0, 0, 0, Location())
	fmt.Println(t2)
}

// 東京のタイムゾーンを取得
//
// @return *time.Location
func Location() *time.Location {
	return time.FixedZone("Asia/Tokyo", 9*60*60)
}
```

https://wandbox.org/permlink/5IHEZbvhJ8a7ZGdU


##参考
[Goで時刻を取り扱う](https://qiita.com/taizo/items/acbee530bd33c803dab4)
[逆引きGolang (日付と時刻)](https://ashitani.jp/golangtips/tips_time.html)