Linux の date コマンドを日本時間に変換したい。ロケールやファイルをいじらず UTC 環境のまま【UTC→JST】

<h2>date コマンド実行時のみ日本時間で表示させたい</h2>

> 自動化のため Git のコミット時のコメントに、ビルド時の日付を UTC でなく日本時間（JST）で記録させたい。
>
> しかし、Alpine の Docker イメージなど、デフォルトが UTC で、ロケールも `asia/tokyo` になっておらず、軽量化のためタイムゾーン・ファイルも `/usr/share/zoneinfo/Asia/` にない。

普通はパッケージを入れるなりすればいいのです。しかし、**ログ的に確認するためだけに Docker イメージにレイヤーを増やしたくない**のです。

[Qiita 記事に絞って「`linux` `date` `変換` `utc` `jst` `日本時間`」とググって](https://www.google.com/search?q=site:qiita.com+linux+date+%E5%A4%89%E6%8F%9B+utc+jst+%E6%97%A5%E6%9C%AC%E6%99%82%E9%96%93&tbs=qdr:y)」もタイトルからストレートにわかる記事がありませんでした。記事を開いてもファイルの修正が必要だったり、すでにロケールが `asia/tokyo` を前提だったりしたので、自分のググラビリティとして。

## TL; DR <sub><sup><sub><sup>（今北産業）</sup></sub></sup></sub>

1. 環境変数 `TZ=-9` を `date` コマンドの前に付ける。
2. 日本時間は `+09:00` と `+9` 進んでいるので `-9` で引いてあげる。
3. **注意**: 設定が `UTC` でなく `JST` なのに `TZ=-9` してしまうと、さらに狂う。

### UTC

```shell-session:デフォルト（現在時刻=日本時間の１２：０８ＰＭ）
$ date
Wed May 29 03:08:21 UTC 2019

$ TZ=-9 date '+%a %b %d %H:%M:%S JST %Y'
Wed May 29 12:08:24 JST 2019
```

### RFC-2822 互換

```shell-session:デフォルト（現在時刻=日本時間の１１：５３ＡＭ）
$ date -R
Wed, 29 May 2019 02:53:05 +0000

$ TZ=-9 date -R
Wed, 29 May 2019 11:53:10 +0900
```

### ISO-8601 互換

```shell-session:デフォルト（現在時刻=日本時間の１２：１９ＰＭ）
$ date -Iseconds
2019-05-29T03:19:26+0000

$ TZ=-9 date -Iseconds
2019-05-29T12:19:45+0900
```

## TS; DR <sub><sup>（コンテナでコンパイる、たかが日本時間にするためだけの細かいこと）</sup></sub>

### Go言語（golang）で Hugo のコンパイル時に日本時刻でビルド時間を渡したかった

Markdown から静的 Web ページを作成する `Jekyll` の golang 版とも言える "[HUGO](https://gohugo.io/)" というフレームワークがあります。いわゆるひとつの[静的サイトジェネレーター](https://ja.wikipedia.org/wiki/%E9%9D%99%E7%9A%84%E3%82%B5%E3%82%A4%E3%83%88%E3%82%B8%E3%82%A7%E3%83%8D%E3%83%AC%E3%83%BC%E3%82%BF%E3%83%BC)というやつです。

これを Docker 上でビルドして使おうと思いました。具体的には Alpine Linux ベースのコンテナ上で動かすために[安定版のソース](https://github.com/gohugoio/hugo/tree/stable)からビルド（コンパイル）して、マルチステージで軽量コンテナ（イメージ）を作ろうとしたのです。

ま、ローカルに軽量の仮想ビルド環境を作りたかったのです。

コンパイルまでは正常にできたのですが、バージョン情報を表示させると、`BuildDate: unknown` とビルドの日付が設定されていませんでした。まぁ、自分でビルドしていて、ビルド日付を渡していないので当然です。

```shell-session:普通にビルド
$ go build -a --ldflags '-extldflags "-static"' -o /go/bin/hugo main.go
...

$ /go/bin/hugo version
Hugo Static Site Generator v0.55.6 linux/amd64 BuildDate: unknown
```

ソースの方をいじってもいいのですが、ビルド時に変数を渡した方がシンプルというものです。

```shell-session:日付データを渡してビルド
$ go build -a \
> --ldflags '-extldflags "-static" -X github.com/gohugoio/hugo/common/hugo.buildDate="hogehoge"' \
> -o /go/bin/hugo main.go
> 
...
$ /go/bin/hugo version
Hugo Static Site Generator v0.55.6 linux/amd64 BuildDate: "hogehoge"
```

しかし、`date` コマンドで取得した値をそのまま渡したのですが、色々と試しているなかで確認しづらかったのです。日本時間ではないためです。いま何時と聞かれても大体な時間もわかりません。

素直にロケールファイルをダウンロードさせれば良いものを、コマンドだけでやろうとしたものだから、探すのに手間取ってしまい、むしろ時間を食ってしまいますた。とほほ。

結局 Dockerfile の `RUN` は以下のような感じに落ち着きました。

```dockerfile:Dockerfile
FROM gliderlabs/alpine:latest AS build

LABEL "MAINTAINER"="KEINOS https://github.com/KEINOS" \
      "URL"=https://github.com/KEINOS/Dockerfile_of_Hugo-Alpine \
      "ORIGINAL AUTHOR"="Johannes Mitlmeier <dev.jojomi@yahoo.com>"

RUN apk add --no-cache git gcc g++ && \
    git clone --branch stable https://github.com/gohugoio/hugo.git hugo && \
    cd hugo && \
    buildDate=$(TZ=-9 date -Iseconds) && \
    go build -a \
      --ldflags "-extldflags \"-static\" -X github.com/gohugoio/hugo/common/hugo.buildDate=${buildDate}" \
      -o /go/bin/hugo main.gohugoio && \
    /go/bin/hugo version

FROM keinos/alpine

COPY --from=build /go/bin/hugo /usr/local/bin/hugo

ENTRYPOINT ["/usr/local/bin/hugo"]
```
- [最新の Dockerfile](https://github.com/KEINOS/Dockerfile_of_Hugo-Alpine) @ GitHub


## 動作確認済み環境

- Alpine Linux v3.9

```shell-session
$ docker run --rm alpine:latest cat /etc/os-release
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.9.4
PRETTY_NAME="Alpine Linux v3.9"
HOME_URL="https://alpinelinux.org/"
BUG_REPORT_URL="https://bugs.alpinelinux.org/"
$ # Over masOS as a host
$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.14.4
BuildVersion:	18E226
```

## 参考文献

- 「[指定したタイムゾーンのローカルタイムを表示する方法・TZ](https://linux.just4fun.biz/?%E9%80%86%E5%BC%95%E3%81%8DUNIX%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89/%E6%8C%87%E5%AE%9A%E3%81%97%E3%81%9F%E3%82%BF%E3%82%A4%E3%83%A0%E3%82%BE%E3%83%BC%E3%83%B3%E3%81%AE%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%82%BF%E3%82%A4%E3%83%A0%E3%82%92%E8%A1%A8%E7%A4%BA%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95%E3%83%BBTZ#he1c0db3)」@ 逆引きUNIXコマンド
- 「[Goでビルドバージョン情報を参照できるようにする(Go1.5)](https://qiita.com/reiki4040/items/6b32370532c3eafe1f0e)」@ Qiita