いろいろ備忘録日記

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

Goメモ-173 (ローカルタイムゾーンを変更)(TZ, time.Local)

概要

あまり使うことは無いと思いますが、しっておくと何かのときに便利かもしれません。

私は普段プライベートな勉強や開発では、GitpodやGithub Codespaceを使って遊んでいます。

で、日付に関しては海外のサーバ上で動いているので、当然ですがタイムゾーンがJSTじゃなくてUTCで表示されます。

普段は全然問題ないのですが、ログに出力するサンプルとかだと時刻がズレすぎていて変な感じになるので

一時的にタイムゾーンをJSTにしたい。logパッケージの日付は、中で time.Now() しており、外から *time.Location を渡せる状態にはなっていません。

なので、以下の2つがやり方としてあるかなと思います。

環境変数 TZ を一時設定

これが一番まともな方法だと思います。

例えば、Gitpod だとデフォルトでは以下です。

gitpod /workspace/try-golang $ date; date -R
Fri 07 Jan 2022 07:39:40 AM UTC
Fri, 07 Jan 2022 07:39:40 +0000

当たり前ですがUTCです。んで、以下のようにすると

gitpod /workspace/try-golang $ export TZ=Asia/Tokyo
gitpod /workspace/try-golang $ date; date -R
Fri 07 Jan 2022 04:40:49 PM JST
Fri, 07 Jan 2022 16:40:49 +0900

となります。なので、Goのプログラムを動かす際に

gitpod /workspace/try-golang $ TZ=Asia/Tokyo make run

とすれば、time.Now() の結果が JST になります。

time.Local の値を変更する

上の方法が如何ともし難い何らかの事情があって出来ない場合は、この方法が使えるかもしれません。

timeパッケージには グローバル変数 として Location という変数が定義されています。

この変数が書き換え可能で、変更すると time.Now() などの結果を強制的にJSTにすることができます。

ただ、あまりやらない方が良いのは確かです。知識として知ってくと便利な扱いですね。

package times

import (
    "log"
    "os"
    "time"
)

// ChangeLocalTimezone -- time.Localを変更して強制的にローカルタイムゾーンを一時的に変更するサンプルです.
//
// REFERENCES
//   - https://pkg.go.dev/time#Location
//   - https://tutuz-tech.hatenablog.com/entry/2021/01/30/192956
//   - https://qiita.com/immrshc/items/a080975c6c7e23498944
func ChangeLocalTimezone() error {
    // Gitpod や Github Codespace などで time.Now() すると
    // タイムゾーンが JST ではなく UTC となる。(海外のサーバ上なので当然)
    //
    // 基本はこれで良いが、logパッケージのサンプルなどを動かすと
    // 時刻がズレすぎていて変なので、一時的にタイムゾーンを変更したい。
    //
    // timeパッケージには グローバル な Local フィールドが存在するので
    // ここを変更すれば強制的にタイムゾーンを変更できる。
    //
    // ただし、いい方法とは言えないので、実務レベルではやらない方が良いと思います。
    // 普通に環境変数 TZ に Asia/Tokyo を設定しておいてプログラムを動作させる方が良いと思います。

    var (
        l = log.New(os.Stderr, "", log.LstdFlags)
    )

    // Gitpod や Github Codespace などで実行すると以下は JST ではなく UTC となる
    l.Printf("[time.Now() -- Default] %v\n", time.Now())

    // 一時的な変更に留めたい場合は後から復活できるようにしておく
    original := time.Local
    defer func() {
        time.Local = original
    }()

    jst, err := time.LoadLocation("Asia/Tokyo")
    if err != nil {
        return err
    }
    time.Local = jst

    // 切り替え後だと、ちゃんとタイムゾーンが適用される
    l.Printf("[time.Now() -- After  ] %v\n", time.Now())

    return nil
}

上記のプログラムを Gitpod などで実行すると以下のようになります。

gitpod /workspace/try-golang $ echo ${TZ}

gitpod /workspace/try-golang $ make run
go run github.com/devlights/try-golang/cmd/trygolang -onetime -example ""

ENTER EXAMPLE NAME: time_changelocaltime

[Name] "time_changelocaltimezone"
2022/01/07 07:49:59 [time.Now() -- Default] 2022-01-07 07:49:59.467272936 +0000 UTC m=+3.904762895
2022/01/07 16:49:59 [time.Now() -- After  ] 2022-01-07 16:49:59.46739467 +0900 JST m=+3.904884570


[Elapsed] 137.427µs

変更前は UTC となっていますが、変更後は JST になっていますね。

参考情報

pkg.go.dev

tutuz-tech.hatenablog.com

qiita.com


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

  • いろいろ備忘録日記まとめ

devlights.github.io

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

  • いろいろ備忘録日記サンプルソース置き場

github.com

github.com

github.com