本記事の概要
Hugoの記事におけるタイムゾーンと、日本時間前提(※)の場合のベストプラクティスについて紹介する初心者向け記事です。
(※)日本時間前提:日本時間(JST:+09:00)前提で、他のタイムゾーンで使用しない。つまり、日本国内のみを前提としたサイト向け
前提
Hugo+Blowfishテーマ適用済みの環境です。
なお、Windowsでの操作を想定しています。
(本記事が属するアドベントカレンダーについてもご確認ください)
覚えておくべきこと
今回の話をするうえで理解しておくと良い事を書いておきます。
- Hugoはgolangの時刻を利用している
- Hugo(golang)の時刻にはタイムゾーン情報を含んでいる
- 従って、過去・未来の判定はタイムゾーンを考慮してくれる
- タイムゾーン情報が無い場合、何らかの方法でタイムゾーンを決める必要がある
記事へ時刻を埋め込む際の方法
FrontMatterのdateパラメーターなどで、記事に作成時刻などを埋め込みますが、その際にタイムゾーンも含めて記載する方が良いです。
つまり、日本時間前提で使用するのならば、+09:00といったように必ず日本時間であることを明記した方が良いです。
Hugoの時刻(未来・過去)の判定はタイムゾーンを考慮してくれるため、ビルド用のマシン(CI環境などを含む)の時刻がUTCなどで動いていた場合でも、公開時刻の判定は意図通りになります。
(無論、ビルド用のマシンの時刻が適切に同期されているとして)
+++
date = "2024-10-02T23:48:08+09:00"
title = "xxx"
+++
UTCで記載する場合とJST(日本時間)で記載する場合の注意
意味合いとして同じ時刻である場合に、
- UTCとJST(日本時間)のどちらを使用しても未来・過去の判定は問題ない
- 時刻から年月日や時・分・秒など度を取り出す処理に差異が出る
ということに注意する必要があります。
例えば、
- UTC 2025年11月30日23時00分00秒
- JST 2025年12月01日08時00分00秒
は、未来・過去という意味では同じ時刻を指してます。(JSTはUTC+09:00のため)
そのため、先のdateにおいても、時刻さえ合っていれば「記事が公開されるか否か」の判定には影響しません。
しかし、Webページの公開日時の表示などは、機械的に年月日や時分秒を取り出すため、
- UTCで書いていると2025年11月30日
- JSTで書いていると2025年12月01日
という風に、公開日時などが変わる場合があります。
(テーマ側でタイムゾーンの補正をしていれば問題ないかもしれませんが、直感に反するためそういうケースは少ないかと思います)
そのため、JST前提のサイトであれば、FrontMatterに埋め込む時刻はJSTで書いた方が良いです。
時刻にタイムゾーンが記載されていない場合の挙動について
例えば、下記のように、FrontMatterに書いてある時刻にタイムゾーンが記載されていない場合を考えてみましょう。
+++
date = "2024-10-02T23:48:08"
title = "xxx"
+++
先にも言った通り、Hugo(golang)の時刻情報は、タイムゾーンも含んでいます。
そのため、タイムゾーンも含めて記載されていれば、その通りに解釈すればよいです。
しかしながら、上記のようにタイムゾーンが書いていない場合、タイムゾーンを推定する必要があります。
(上記の例で言えば、どのタイムゾーンにおける2024年10月02日23時48分08秒なのか)
Hugoにおいて「タイムゾーンが記載されていない時刻に対してどのタイムゾーンで書かれているとして解釈するか」は、timeZoneというtomlのコンフィグパラメーターで決まります。
特に指定していなければ、timeZoneにUTCが設定されているとして解釈されますが、timwZoneパラメーターにタイムゾーンを指定すれば、そのタイムゾーンで解釈されます。
タイムゾーンを明記して記載した時刻は、timeZoneパラメーターの値に関係なく、時刻に記載されたタイムゾーンで解釈されます。
下記の公式サイトの記載も参考にしてください。
日本時間にしたければ、"Asia/Tokyo"にすればよいです。
なお、Blowfishテーマにおいては言語ごとにtimeZoneを設定できるので、languages.ja.tomlに書くことが出来ます。
# Hugo側の記事の日付にタイムゾーンがついていない場合のタイムゾーン
timeZone = "Asia/Tokyo" # 日本時間扱いにしたいのでAsia/Tokyo
JST前提におけるベストプラクティスとしては、
- 元々dateでタイムゾーンを指定しているため、timeZoneコンフィグは指定しなくても問題ない
- ただし、何らかの事情でタイムゾーンを書きそびれた場合のフォールバックとして、timeZoneに"Asia/Tokyo"を指定しておくと安全
と言えるでしょう。
Hugoにおける時刻関連関数のタイムゾーン指定省略時について
ちなみに、time.AsTime関数やtime.Format関数ににおいてタイムゾーンの指定を省略した場合、tomlでの設定値が使われるようなので、考慮しておくと良いかもしれません。
詳しくは下記の公式サイトの記載を参考にしてください。
time.Nowの値について
Hugoにはtime.Now関数があり、これを利用するとビルド時の現在時刻が取得できます。
詳細は下記の公式サイトを参照してください。
time.Nowで取得される時刻のタイムゾーンは、使用するマシン(OS)に設定されたタイムゾーンなので注意してください。
つまり、手元の作業用PCは日本時間(JST)で設定されているが、CI環境のビルドマシンはUTCで設定されているため、作業用PCとCI環境(本番環境)で結果が異なるといったことが起きえます。
Cloudfrare Pagesの場合、ビルド(CI)環境でTime.Nowを実行した場合のタイムゾーンは、デフォルトではUTCになっています。(設定方法は後述します)
つまり、JST前提でのベストプラクティスとしては下記になります。
- (ShortCodeなどの)実装時:time.Nowで取得された時刻のタイムゾーンがJSTと仮定しない
- time.AsTimeで明示的にタイムゾーンを変換してから使用する
- 運用時:各環境でのタイムゾーン設定を合わせる(JSTにする)
- 細かい設定方法はOSなどに依存するので注意
補足:Cloudflare PagesのCI環境のタイムゾーン
Cloudflare PagesのCI環境では、一般的なLinuxマシンのようにTZ環境変数にタイムゾーンを設定することで、ビルド環境のタイムゾーンを設定できます。
wrangler.tomlでTZ環境変数を設定できるので、下記の例のようにTZに"Asia/Tokyo"としておけば、time.NowのタイムゾーンもJSTになります。
[vars]
HUGO_VERSION = "0.152.2"
NODE_VERSION = "24"
TZ = "Asia/Tokyo"
[env.production.vars]
HUGO_VERSION = "0.152.2"
NODE_VERSION = "24"
TZ = "Asia/Tokyo"
まとめ
Hugo(golang)での時刻は、タイムゾーンを意識したうえで考えましょう。
そのためには
- 可能な限りタイムゾーンを明記して使用するようにする
- time.NowなどHugoの記事外から時刻を取る際はtime.AsTimeでタイムゾーンを変換する
といった形にすると良いです。