Help us understand the problem. What is going on with this article?

Go/golangでの日付処理まとめ(チートシート)

More than 1 year has passed since last update.

この記事は全部俺 Advent Calendar 2018の20日目の記事です。
Goの日付関連の処理についてまとめます。

Goの日付処理チートシート

パース編(文字列 → 日付型)

フォーマットが明確なとき

import "time"
time.Parse("20060102", "20181220")                                            // => 2018-12-20 00:00:00 +0000 UTC
time.Parse("20060102150405", "20181220123456")                                // => 2018-12-20 12:34:56 +0000 UTC
time.Parse("2006/01/02 15:04:05.000", "2018/12/20 12:34:56.123")              // => 2018-12-20 12:34:56.123 +0000 UTC
time.Parse("2006-01-02T15:04:05.000000Z", "2018-12-20T12:34:56.123456Z")      // => 2018-12-20 12:34:56.123456 +0000 UTC
time.Parse("Mon, 02 Jan 2006 15:04:05 MST", "Thu, 20 Dec 2018 12:34:56 GMT")  // => 2018-12-20 12:34:56 +0000 GMT
time.Parse("Mon Jan 2 15:04:05 MST 2006", "Thu Dec 20 12:34:56 JST 2018")     // => 2018-12-20 12:34:56 +0900 JST

参考:日付フォーマットの詳細については、こちらを参照してください。
ちなみに、なぜフォーマットが2006/01/02 15:04:05 MSTなのかというと、これは形式を変えて書く(アメリカ式の時刻の順番で書く)と01/02 03:04:05PM '06 -0700となるからだそうです。(MSTは山岳部標準時で-0700となるらしいです。)

雑にパースしたいとき/フォーマットが明確でないとき

import "github.com/Songmu/go-httpdate"
httpdate.Str2Time("20181220", nil)                       // => 2018-12-20 00:00:00 +0900 JST
httpdate.Str2Time("20181220123456", nil)                 // => 2018-12-20 12:34:56 +0900 JST
httpdate.Str2Time("2018/12/20 12:34:56.123", nil)        // => 2018-12-20 12:34:56.123 +0900 JST
httpdate.Str2Time("2018-12-20T12:34:56.123456Z", nil)    // => 2018-12-20 12:34:56.123456 +0000 UTC
httpdate.Str2Time("Thu, 20 Dec 2018 12:34:56 GMT", nil)  // => 2018-12-20 12:34:56 +0000 GMT
httpdate.Str2Time("Thu Dec 20 12:34:56 JST 2018", nil)   // => 2018-12-20 12:34:56 +0900 JST

第2引数のloc(ロケーション)にnilを入れた場合、文字列でタイムゾーンが指定されていない場合はローカル環境に依存します。
ここではJSTで出力されていることに注意です。

パース編(日付型 → 文字列型)

import "time"
t := time.Date(2018, 12, 20, 12, 34, 56, 123456, time.UTC)
t.Format("20060102")                                   // => 20181220
t.Format("20060102150405")                             // => 20181220123456
t.Format("2006/01/02 15:04:05.000")                    // => 2018/12/20 12:34:56.000
t.Format("2006-01-02T15:04:05.000000000Z")             // => 2018-12-20T12:34:56.000123456Z
t.Format("Mon, 02 Jan 2006 15:04:05 MST")              // => Thu, 20 Dec 2018 12:34:56 UTC
t.Format("Mon Jan 2 15:04:05 MST 2006")                // => Thu Dec 20 12:34:56 UTC 2018

タイムゾーンの処理

import "time"
// ローカルでの現在時刻取得(デフォルトロケール:'ja_JP'での例)
time.now()                                                 // => 2018-12-20 22:43:49.764662 +0900 JST m=+0.000477630
time.Now().UTC()                                           // => 2018-12-20 13:44:06.781869 +0000 UTC

// タイムゾーンの変換
// UTC → JST
t := time.Date(2018, 12, 20, 12, 34, 56, 123456, time.UTC) // => 2018-12-20 12:34:56.000123456 +0000 UTC
loc, err := time.LoadLocation("Asia/Tokyo")
if err != nil {
    loc = time.FixedZone("Asia/Tokyo", 9*60*60)
}
t = t.In(loc)                                              // => 2018-12-20 21:34:56.000123456 +0900 JST
// JST → UTC
t.UTC()                                                    // => 2018-12-20 12:34:56.000123456 +0000 UTC

演算編

日付 + 期間 or 日付 - 期間

import "time"
t := time.Date(2018, 12, 20, 12, 34, 56, 123456, time.UTC) // => 2018-12-20 12:34:56.000123456 +0000 UTC
t.AddDate(0, 0, 1)                                         // => 2018-12-21 12:34:56.000123456 +0000 UTC
t = time.Date(2018, 12, 20, 12, 34, 56, 123456, time.UTC)  // => 2018-12-20 12:34:56.000123456 +0000 UTC
t.AddDate(0, 0, -1)                                        // => 2018-12-19 12:34:56.000123456 +0000 UTC
t = time.Date(2018, 12, 20, 12, 34, 56, 123456, time.UTC)  // => 2018-12-20 12:34:56.000123456 +0000 UTC
t.AddDate(1, 1, 1)                                         // => 2020-01-21 12:34:56.000123456 +0000 UTC

月初・月末

import "time"
// 今月の月初
time.Date(2018, time.Now().Month(), 1, 0, 0, 0, 0, time.Local)                       // => 2018-12-01 00:00:00 +0900 JST
// 今月の月末
time.Date(2018, time.Now().Month(), 1, 0, 0, 0, 0, time.Local).AddDate(0, 1, -1)     // => 2018-12-31 00:00:00 +0900 JST
// 先月の月初/月末
time.Date(2018, time.Now().Month() - 1, 1, 0, 0, 0, 0, time.Local)                   // => 2018-11-01 00:00:00 +0900 JST
time.Date(2018, time.Now().Month() - 1, 1, 0, 0, 0, 0, time.Local).AddDate(0, 1, -1) // => 2018-11-30 00:00:00 +0900 JST
// 来月の月初/月末
time.Date(2018, time.Now().Month() + 1, 1, 0, 0, 0, 0, time.Local)                   // => 2018-11-01 00:00:00 +0900 JST
time.Date(2018, time.Now().Month() + 1, 1, 0, 0, 0, 0, time.Local).AddDate(0, 1, -1) // => 2018-11-30 00:00:00 +0900 JST

ちなみにmonthに13を入れても問題なく動作するので、12月でも大丈夫です。
time.Date(2018, 13, 1, 0, 0, 0, 0, time.Local) => 2019-01-01 00:00:00 +0900 JST

週数の判定

import "time"
t := time.Date(2018, 12, 20, 12, 34, 56, 123456, time.UTC) // => 2018-12-20 12:34:56.000123456 +0000 UTC
# その日が年の何周目にあたるのか(月曜始まり)
y, w := t.ISOWeek()  // y => 2018, w => 51
// その日が月の何週目にあたるのか(月曜始まり)
// 月初日の週数を出して減算する
_, firstW := time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, t.Location()).ISOWeek()
w - firstW + 1       // => 4

曜日の判定

import "time"
t := time.Date(2018, 12, 20, 12, 34, 56, 123456, time.UTC) // => 2018-12-20 12:34:56.000123456 +0000 UTC
// 日曜始まりの日本語定数リストを作成
jweek := [7]string{"日", "月", "火", "水", "木", "金", "土"}
t.Weekday()        // => Thursday
jweek[t.Weekday()] // => 木

まとめ

Goの文字列日付パースは独特の記法なので慣れが必要そうです。
先にフォーマットの方から記載するのもPython3系とは逆なのでしょっちゅう間違えます。頑張って慣れていきたい。

今後も思いついたら適宜追加していく予定です。
指摘・修正や編集リクエストもお待ちしております!

tez
libora
e-Learning一括検索サービス『LIBORA』の開発・運営を行っています。
https://libora.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした