UTCの日時を日付だけに切ってから集計すると、日本時間の一日とずれることがあります。たとえばUTCの10月31日15時は、UTC+09:00では11月1日0時です。同じ一件でも、どちらの時刻で日付を決めるかによって集計先が変わります。
日本時間の日別表を作るなら、日本時間へ変換してから日付を取り出す順にします。日時の文字列から最初の十文字だけを切る方法では、時差を反映できません。
オフセット付きの日時を変換する
次は三件の架空の日時です。+00:00というUTCオフセットを含む文字列をdatetimeへ変換し、JSTを固定のUTC+09:00として指定します。実際のAPIへの接続はありません。
from collections import Counter
from datetime import datetime, timedelta, timezone
jst = timezone(timedelta(hours=9), name="JST")
values = [
"2026-10-31T14:59:59+00:00",
"2026-10-31T15:00:00+00:00",
"2026-11-01T00:00:00+00:00",
]
counts = Counter()
for value in values:
stamp = datetime.fromisoformat(value)
if stamp.utcoffset() is None:
raise ValueError("タイムゾーンのない日時です")
day = stamp.astimezone(jst).date()
counts[day.isoformat()] += 1
for day, count in sorted(counts.items()):
print(day, count)
assert counts == {"2026-10-31": 1, "2026-11-01": 2}
日本時間では10月31日が一件、11月1日が二件になります。UTCの日付のまま数えると10月31日が二件になるため、日別表が違います。Windows・Python 3.12.10で、この境界の三件を確認しました。
例ではCounterという件数を数える道具を使っています。金額の日別合計を作る場合も、どの日へ入れるかを確定してから足す順序は同じです。元の日時と変換後の日付を一緒に確認できるようにすると、差が出た明細を探せます。
タイムゾーンなしの値を推測しない
2026-11-01T00:00:00のように、オフセットを持たない日時からは、UTCか日本時間かを文字列だけで判断できません。この例では、その値が来たら停止する条件にしています。
Pythonのastimezoneは、タイムゾーンのない日時を実行環境のローカル時刻とみなす動作があります。パソコンの設定に依存した結果を避けるため、入力にオフセットがあるかを先に確認しています。
入力元が「タイムゾーン表記は省略するが値はUTC」と定義しているなら、その仕様に従って情報を付ける処理を別に作れます。定義を確かめず、すべての日時をUTCとして扱うことはしません。
付け替えと変換を分ける
replace(tzinfo=…)は日時の表示される時刻を変換する操作ではありません。すでに別の時刻帯を表している値へJSTを付けるだけでは、同じ瞬間を表す日本時間になりません。
この記事のastimezone(jst)は、元の瞬間を保って時刻帯を変換します。ログへ保存するときも、元のUTC日時を残すのか、オフセット付きの変換値を残すのかを決めてください。日付だけへ減らすと、後から時差を再確認できなくなります。
海外拠点など夏時間のある地域を含める場合は、固定オフセットのJSTの例をそのまま流用せず、地域のタイムゾーンを扱う方法を選びます。
API由来の日時を保存する流れはJSONの読み方と保存、集計値の検算はCSV集計の基本で補えます。
参考資料
Python datetime公式資料を2026年11月1日に確認しました。
