関連記事
GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ
概要
以下、自分用のメモです。よく忘れるのでここにメモメモ。。。
上記の書籍に 翌月の日付を求めるというTipsが載っていました。
Goのtimeパッケージでは日付の正規化処理が内部で行われるので、月の末日が現在日時である場合に、翌月を求めると違う答えになってしまうことがあります。
大抵、その場で計算するコード書いて済ませてしまっているので、ついでにここにメモしておきます。
サンプル
package times import ( "time" "github.com/devlights/gomy/output" ) // CalcNextMonth は、翌月の日付を求めるサンプルです。 // // # REFERENCES // - https://pkg.go.dev/time@go1.21.4 func CalcNextMonth() error { // // 日付が範囲外の存在しない値になったとき、Goはその値を存在する日付に変換する。 // この変換を「正規化」という。なので、翌月を求める際に元の値によっては // 翌々月となってしまうことがある。 // const ( LOC = "Asia/Tokyo" ) var ( jst, _ = time.LoadLocation(LOC) original = time.Date(2023, 10, 31, 0, 0, 0, 0, jst) ) output.Stdoutl("[original]", original.Format(time.RFC3339)) // // 11月には31日が存在しないため // そのままAddDateすると、正規化されて12月02日となってしまう。 // var ( nextMonth1 = original.AddDate(0, 1, 1) ) output.Stdoutl("[nextmonth1]", nextMonth1.Format(time.RFC3339)) // // ちゃんと計算して求めるやり方 (書籍「実用 GO言語」) // 年月日以外の部分(時分秒とナノ秒)は面倒なので0固定 // var ( year, month, day = original.Date() // 元の日付 first = time.Date(year, month, 1, 0, 0, 0, 0, jst) // 元の日付の月初 year2, month2, _ = first.AddDate(0, 1, 0).Date() // 月初の値を使って翌月の年と月を取得 nextMonth2 = time.Date(year2, month2, day, 0, 0, 0, 0, jst) // 元の日付の日を当てて翌月値を仮作成 ) if month2 != nextMonth2.Month() { // 正規化が発生して翌々月になってるので調整 // - 2月進めて1日戻すと翌月の末日になる nextMonth2 = first.AddDate(0, 2, -1) } output.Stdoutl("[nextmonth2]", nextMonth2.Format(time.RFC3339)) return nil }
実行すると以下のようになります。
$ task task: Task "build" is up to date task: [run] ./try-golang -onetime ENTER EXAMPLE NAME: time_calc_nextmonth [Name] "time_calc_nextmonth" [original] 2023-10-31T00:00:00+09:00 [nextmonth1] 2023-12-02T00:00:00+09:00 [nextmonth2] 2023-11-30T00:00:00+09:00 [Elapsed] 509.55µs
参考情報
Goのおすすめ書籍
上の書籍の日本語版が下です。
過去の記事については、以下のページからご参照下さい。
サンプルコードは、以下の場所で公開しています。