はじめに
Kubernetes Cronjob で前日分の集計処理を日次バッチで実行していたのですが、なぜか出力結果が前日分になっていました。原因はタイムゾーンが想定と異なっていたからでした。何が問題だったのか備忘録として残しておきます。
問題のコード
前日分の処理をするので、以下のように対象日を取得していました。
from datetime import datetime, timedelta
target_date = (datetime.now() - timedelta(1)).strftime("%Y-%m-%d")
このバッチを日本時間の午前1時に実行していたとします。もし datetime.now() が日本時間での日にちを返していれば、target_date は前日の日にちを得ることができます。しかし UTC だとしたらどうでしょう?datetime.now() は前日の午後4時となりますので、そこから 1 日前は前々日になってしまいます。これが私のバッチで起きていた問題でした。
対処方法
サーバのタイムゾーンをいちいち把握してからプログラムを調整するのは面倒です。そこで以下のように修正しました。
from datetime import datetime, timedelta, timezone
today_jst = datetime.now(timezone.utc) + timedelta(hours=9)
target_date = (today_jst - timedelta(1)).strftime("%Y-%m-%d")
結び
注意深く考えれば、ごくごく当たり前のことなので、私のチョンボに他なりません。とはいえ、日次バッチのプログラムを書いていると、うっかりやってしまいそうなミスなので、ドキュメントとして残すことにしました。