Alpine LinuxにインストールしたLuaTeXでコンパイル時刻を取得する

# はじめに

$\mathrm{\LaTeX}$文書をAlpine Linuxにインストールした$\mathrm{Lua\TeX}$でコンパイルするにあたって、成果物のPDFにコンパイルされた時刻を埋め込んでいた。しかし、環境変数などを変更したとしてもJSTによる時間が取得できなかったため、やや強引な方法で解決した。なお、この記事のソースコードは次のリポジトリに置かれている。

- https://github.com/y-yu/datetime2-alpine-linux

この記事を読んで疑問や改善するべきところを見つけた場合は気軽にコメントなどで教えて欲しい。

# 環境構築

環境構築は実験に利用した[Dockerfile](https://github.com/y-yu/datetime2-alpine-linux/blob/master/Dockerfile)を参照して欲しい。上記リポジトリのREADMEに従うことで、実験用の環境を構築できる。

# コンパイル時刻の取得

$\mathrm{\LaTeX}$で時刻を得る方法は調べると色々あるが、ここでは[datetime2](https://www.ctan.org/pkg/datetime2?lang=en)というパッケージを利用することとする。datetime2パッケージの詳しい使い方は割愛するとして、次のようにすることでコンパイルされた時間を得ることができる。

```latex:dtmnow.tex
\documentclass{article}
\usepackage{datetime2}

\begin{document}

Now is \DTMnow.

\end{document}
```

これをたとえばmacOSでコンパイルすると次のようになる。

<img width="800" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/10815/5234f226-2a99-e000-e774-2cb89f0014ed.png">

一方で、これをAlpine Linuxでコンパイルすると次のようになってしまう。

<img width="766" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/10815/d9e2c254-5bfc-8e9d-f31d-e703c0cc98d5.png">

このようにタイムゾーンの設定が反映されずJSTではない時間が表示される。[datetime2パッケージのドキュメント](ftp://ftp.kddilabs.jp/CTAN/macros/latex/contrib/datetime2/datetime2.pdf)によると、Luaを利用してタイムゾーンを取得しているしていることが分ったため、原因調査のためにAlpine LinuxにLuaをインストールして次のようなコマンドを叩いたが、正常にタイムゾーンを返している。

```lua
> print(os.date("%z"))
+0900
```

また、$\mathrm{Lua\TeX}$で`\directlua`を用いて上記のコマンドを実行してみたところ、`0000`のような間違ったタイムゾーンが得られたので、$\mathrm{Lua\TeX}$のLuaを用いて正しいタイムゾーンを得ることは不可能だと判断した。
さらに、Googleで検索するとヒットする環境変数`TZ`を変更する方法も効果がなかった。

# 解決方法

datetime2パッケージのドキュメントを読むと、特定の条件に合致する場合はtexosqueryパッケージを利用してOSのタイムゾーンや時刻を取得すると書かれていた。texosqueryパッケージはJavaで実装されたアプリケーションを$\mathrm{Lua\TeX}$から起動して時刻といったOSの情報を取得する。ただ、datetime2パッケージのソースコードを読んだところフラグなどで常にtexosqueryパッケージを利用するといった設定ができそうになかったので、次のように無理やりtexosqueryパッケージを呼ぶことにした。ただし、外部のコマンドを実行するため`mwe.tex`のコンパイルには`--shell-escape`オプションが必要である。

```latex:mwe.tex
\documentclass{article}

\usepackage{texosquery}
\usepackage{datetime2}

\DTMsavenow{normal}

% 時間を強制的にtexosqueryで取得する
\makeatletter
\TeXOSQueryNow{\dtm@pdfcreationdate}
\expandafter\@dtm@parsepdfdatetime\dtm@pdfcreationdate\@dtm@endparsepdfdatetime
\let\@dtm@currentyear\@dtm@year
\let\@dtm@currentmonth\@dtm@month
\let\@dtm@currentday\@dtm@day
\let\@dtm@currenthour\@dtm@hour
\let\@dtm@currentminute\@dtm@minute
\let\@dtm@currentsecond\@dtm@second
\let\@dtm@currenttimezonehour\@dtm@timezonehour
\let\@dtm@currenttimezoneminute\@dtm@timezoneminute
\makeatother

\DTMsavenow{texosquery}

\begin{document}

Now is \DTMuse{normal} (normal).

Now is \DTMuse{texosquery} (TeXOSQuery).

\end{document}
```

これの結果は次のようになる。

<img width="817" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/10815/6a836ae4-3358-b770-d6f3-25f576e46df9.png">

このようにtexosqueryパッケージを利用した方法では正しくタイムゾーンが取得できていることが分かる。

# まとめ

Alpine Linuxでdatetime2パッケージを利用すると正しく時刻（タイムゾーン）を取得できない理由は分からなかったが、とりあえず強引な方法で解決することができてよかった。余談だがこれにより自分が関わっている同人誌をDockerイメージ内でヒラギノフォントを埋め込みつつコンパイルする目処がたった。

# 追記

<blockquote class="twitter-tweet" data-conversation="none" data-lang="ja"><p lang="ja" dir="ltr">TZ=Asia/Tokyo は「&#39;$TZDIR/Asia/Tokyo&#39;を見に行く」という意味なので、大本のtzdataを消しているとダメなようです。ただ、TZは絶対パス指定も可能なので、TZ=/etc/localtime も使えるようです。</p>&mdash; ZR-TeXnobabbler（ﾁﾘｰﾝ🔔 (@zr_tex8r) <a href="https://twitter.com/zr_tex8r/status/907227968535093248?ref_src=twsrc%5Etfw">2017年9月11日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 参考文献

- [datetime2 (CTAN)](https://www.ctan.org/pkg/datetime2?lang=en)
- [texosquery (CTAN)](https://www.ctan.org/pkg/texosquery?lang=en)