emahiro's ProgrammingBlog

勉強記録と書評とたまに長めの呟きを書きます

GoのtimeのFormat表記方法でハマったこと

GolangUnixタイムをISO8601形式に変換したいということがあって、実際に返還する際にFormatの指定の仕方でかなりハマりました。

こういった方の記事を参考にしたらすぐわかったのですが、

GO言語での日付処理

そもそもGoで時刻表記をするときにちょっとクセがあるのでメモとしてまとめてます。

GAE上では必ずUTC

最初にローカルで time を使ったときはJSTだったのですが、GAE上で動かしたときは自動的にUTCになってしまうので、JSTに変換しなければならない、というところでハマりました。
TimeZone動向の話ではないんですね。

なので日本時間に合わせます。

import time

func main () {

    var (
        location := time.FixedZone("Asia/Tokyo", 9*60*60)
        now := func() time.Time { return time.Now().In(location) }
    )

    fmt.Printf("%v", now.Format(time.RFC3339))

}

独特なフォーマットの表記方法

日本時間への変更でも記述してありますが、goで指定した形式への変換は time.Format を使います。
ここで、RFC3339 ではなく、明示的にISO8601形式に変えます。

通常の言語であれば、年をY、月をMみたいに形式が決まっています。 なので、goでも同じことしようとしたらgoでは明示的に 2000-01-01T01:00:00+09:00 みたいに書式の結果で形式を指定します。 そこで試しに、表示させたい形式を適当に作ってみたところ。

now := time.Now()
fmt.Printf("%s", now.Format("2000-01-01T01:00:00+09:00"))

// 7074-09-78T77:79:14+07:00 ????

なんかよくわからない形式になってて、変換が失敗している…

ここでどうして変換したい書式を指定してもうまくいかないのか結構ハマりました。

結論としては goでのtimeのformat変換では使える文字が決まっている っていうことになります。

どういうことかというとgoのTimeパッケージのドキュメントを見るとかいてありました。
time - The Go Programming Language

変換したいフォーマットで使えるのは年なら Y ではなく 2006 みたいな感じです。

now := time.Now()
fmt.Printf("%s", now.Format("2006-01-02T15:04:05+09:00"))
// 2017-7-12T22:24:43+09:00

ちゃんと変換できました。

※ ISO8601形式で +09:00 と表記する形式は標準パッケージには用意されてなかったので、自前で書いてます。

このフォーマットの一覧はtimeパッケージの format.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"
)