Go
golang

Go 言語における無効日付(2月31日など)の扱い

各言語における無効日付(2月31日など)の扱い」のコードを真似て Go 言語で検証してみる。

package main

import (
    "fmt"
    "time"
)

func main() {
    tm := time.Date(2017, 1, 31, 0, 0, 0, 0, time.UTC)
    for i := 0; i < 6; i++ {
        fmt.Println(tm.Format("2006-01-02"))
        tm = tm.AddDate(0, 1, 0)
    }
}

結果は以下の通り。

2017-01-31
2017-03-03
2017-04-03
2017-05-03
2017-06-03
2017-07-03

JavaScript と同じですね。
ただし AddDate() メソッドは tm の値を破壊しないので

package main

import (
    "fmt"
    "time"
)

func main() {
    tm := time.Date(2017, 1, 31, 0, 0, 0, 0, time.UTC)
    for i := 0; i < 6; i++ {
        fmt.Println(tm.AddDate(0, i, 0).Format("2006-01-02"))
    }
}

と書けば

2017-01-31
2017-03-03
2017-03-31
2017-05-01
2017-05-31
2017-07-01

と出力される。
これは PHP と同じかな。

なお末日に限るなら, Go 言語では「翌月0日」が「当月末日」と評価されるため

package main

import (
    "fmt"
    "time"
)

func main() {
    tm := time.Date(2017, 1, 31, 0, 0, 0, 0, time.UTC)
    for i := 0; i < 6; i++ {
        fmt.Println(tm.Format("2006-01-02"))
        tm = time.Date(tm.Year(), tm.Month()+2, 0, 0, 0, 0, 0, time.UTC)
    }
}

とすれば

2017-01-31
2017-02-28
2017-03-31
2017-04-30
2017-05-31
2017-06-30

と綺麗に末日を出力できる。ちなみに年をずらして

tm := time.Date(2016, 1, 31, 0, 0, 0, 0, time.UTC)

と閏年でやってみても結果は

2016-01-31
2016-02-29
2016-03-31
2016-04-30
2016-05-31
2016-06-30

と正しく出力される。

参考