いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

Goメモ-359 (翌月の日付を求める)

関連記事

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のおすすめ書籍

Go言語による並行処理

Go言語による並行処理

Amazon

上の書籍の日本語版が下です。


過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。