LoginSignup
50
33

More than 5 years have passed since last update.

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

Posted at

この記事は全部俺 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系とは逆なのでしょっちゅう間違えます。頑張って慣れていきたい。

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

50
33
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
50
33