Hugoで当日の記事が朝9時まで出ない。日付をUTCで読むtimeZoneの既定とbuildFuture
朝に書いた記事をpushして、GitHub Actionsのビルドも緑色で終わったのに、サイトのどこにも記事が出てこない。ビルドのログを見てもエラーも警告もなく、記事のファイルはリポジトリにきちんと入っている。このブログも、立ち上げてすぐのころに一度これを踏んだ。原因は、Hugoが日付を読むときのタイムゾーンと、未来の日付の記事を除外するbuildFutureの組み合わせにあった。 同じところで二度迷わないように、仕組みと直し方をまとめておく。手元のWindows 11に入っているHugo v0.166.0(GitHub Actions側も同じ版)で、最小構成のサイトを作って症状を再現し、どの書き方なら出てどの書き方なら消えるのかを確かめた。結論を先に書くと、設定ファイルにtimeZone = 'Asia/Tokyo'を1行足すか、記事の日付に+09:00を付ければ直る。ただし、どちらも知らないまま運用すると、日本の朝の時間帯にだけ起きる分かりにくい不具合になる。 Hugoは時刻のない日付を、UTCの0時として読む グリニッジ天文台の門の脇にある24時間表示の時計。Hugoが既定で使うUTCは、この天文台を通る子午線の時刻(グリニッジ標準時)の後継にあたるPhoto: Alvesgaspar / CC BY-SA 3.0 記事のfront matterにdate: 2026-10-16と書いたとき、そこには時刻もタイムゾーンも入っていない。人間はそれを「日本の10月16日」と読むが、Hugoには日本で書かれたことを知る手段がない。そこでHugoは、設定ファイルのtimeZoneを見て、その地域の時刻として解釈する。そしてtimeZoneを書いていないときの既定はUTC(協定世界時)になっている。 つまり2026-10-16は、何も設定していなければ「UTCの10月16日0時」、日本時間に直すと10月16日の午前9時として扱われる。date: 2026-10-16T07:00:00のように時刻まで書いても、オフセットが無ければ同じで、UTCの7時、日本時間の16時と読まれる。書いた本人の感覚より、ちょうど9時間うしろにずれる計算だ。 もうひとつ見落としやすいのが、Hugoを動かしているパソコンのタイムゾーンは関係しないという点だ。手元のパソコンは日本時間で動いているが、それでもtimeZoneが無ければUTCとして読まれた。環境変数のTZにAsia/Tokyoを入れて試しても、日付の解釈は変わらなかった。日付をどう読むかは、Hugoの設定だけで決まる。 buildFutureの既定はfalse。未来の記事は何も言わずに外される Hugoには、公開日が未来の記事をビルドに含めない仕組みがある。予約投稿のような使い方を想定したもので、設定のbuildFutureが既定でfalseになっている。下書きを外すbuildDrafts、有効期限が過ぎた記事を外すbuildExpiredも同じく既定はfalseだ。 ここで先ほどのずれが効いてくる。日本時間の10月16日の朝7時30分は、UTCではまだ10月15日の22時30分だ。この時点でdate: 2026-10-16の記事をビルドすると、Hugoから見れば「UTCの16日0時」はまだ1時間半先の未来なので、記事はビルドから外される。日付だけの記事なら、日本時間の0時から9時までの9時間、当日の記事が必ず未来扱いになる。 困るのは、このとき何の知らせも出ないことだ。手元で--logLevel infoを付けてビルドしても、外された記事についての警告は1行も出なかった。出力の最後に表示されるページ数の表が少し小さくなっているだけで、ビルド自体は成功として終わる。GitHub Actionsのログも同じで、緑色のチェックが付いたまま記事だけが無い、という状態になる。 さらに、静的サイトなので、外された記事はあとから勝手に現れたりしない。朝7時にpushしたビルドで外れた記事は、9時を過ぎても、次に誰かがpushしてビルドが走るまでサイトに出てこない。昼に別の記事を足したら、朝の記事が一緒に現れた、という形で気づくことも多いと思う。 手元で再現する。5つの日付の書き方を比べた 再現には、テーマを入れない空のサイトをhugo new siteで作り、記事を5つ置いた。テンプレートは記事のタイトルと日付を並べるだけのものにしている。日本時間10月16日の7時31分(UTCでは15日の22時31分)に、timeZoneの有無でどれがビルドに残るかを見た。 記事 front matterのdate timeZoneなし timeZone = 'Asia/Tokyo' A 2026-10-16 外れる 出る B 2026-10-16T07:00:00 外れる 出る C 2026-10-16T07:00:00+09:00 出る 出る D 2026-10-15 出る 出る E "2026-10-16"(文字列で囲む) 外れる 出る timeZoneが無いとき、AとBとEは未来扱いになり、出力されたのはCとDの2本だけだった。引用符で囲んで文字列として書いても、扱いは日付のときと変わらない。+09:00を付けたCだけは、設定に関係なくいつでも正しく日本時間として読まれる。前日の日付のDは、UTCで読んでもすでに過去なので問題にならない。 timeZone = 'Asia/Tokyo'を足すと、5本すべてが日本時間として読まれ、全部ビルドに残った。どの記事がどの時刻として読まれているかは、hugo list allを実行すると、記事ごとのdateとpublishDateが一覧で出るので一目で分かる。今回の実験では、publishDateを書いていない記事は、dateと同じ値がそのまま入っていた。未来扱いで外れている記事だけを見たいときはhugo list futureが便利だ。 ...