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


はじめに

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

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

環境構築

環境構築は実験に利用したDockerfileを参照して欲しい。上記リポジトリのREADMEに従うことで、実験用の環境を構築できる。

コンパイル時刻の取得

$\mathrm{\LaTeX}$で時刻を得る方法は調べると色々あるが、ここではdatetime2というパッケージを利用することとする。datetime2パッケージの詳しい使い方は割愛するとして、次のようにすることでコンパイルされた時間を得ることができる。

dtmnow.tex
\documentclass{article}
\usepackage{datetime2}

\begin{document}

Now is \DTMnow.

\end{document}

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

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

このようにタイムゾーンの設定が反映されずJSTではない時間が表示される。datetime2パッケージのドキュメントによると、Luaを利用してタイムゾーンを取得しているしていることが分ったため、原因調査のためにAlpine Linuxに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オプションが必要である。

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}

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

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

まとめ

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

追記

参考文献