AIで海外売上CSVを日別集計する方法|現地日付と夏時間を確認

UTCの架空売上5件をニューヨークの日付へ変換。重複する1時30分、25時間の暦日、終了境界を確認し、ID別変換表と日別合計を照合します。

AIものさし編集部

海外の売上CSVをAIで日別集計するときは、「どの時刻を、どの地域の日付として数えるか」を先に決めます。UTCの文字列から日付だけ切り出す方法と、現地時刻へ変換してから日付を取る方法では、同じデータでも日別の合計が変わります。

この記事では、UTCで記録された架空の売上5件を、ニューヨークの暦日へ変換します。夏時間が終わる日に同じ1時30分が二度現れる例を使い、ID、時差、対象期間を残した確認表を作ります。実売上やAIサービスを使った分析結果ではありません。

売上の日付を決める列と地域を固定する

注文、決済、出荷、返金の時刻は別のイベントです。今回は「決済が確定した時刻」を集計する前提とし、すべて同一通貨USD、金額はこの説明用データの値をそのまま合計します。税、為替、返金、キャンセルの会計処理を決める記事ではありません。

元の時刻はUTCと定義し、集計先はAmerica/New_Yorkとします。端末の現在地や、CSVを開いた人のタイムゾーンで日付を決めません。店舗ごとに地域が違う場合は、一つの地域へまとめるのか、店舗別の営業日を使うのかを先に決めます。

表は横にスクロールできます

先に決める項目今回の例
レコードの単位一つの確定決済、一つのevent_id
元の時刻paid_at_utc。末尾ZはUTCとして扱う
集計する日付America/New_Yorkの暦日
日付の境界現地0時以上、翌日0時未満
金額全件USD。今回は除外・返金・換算なし

現地の午前5時を締めにするなど、業務で別の境界を使う場合は今回と異なります。「現地日付にしたから正しい」とせず、レポートの定義へ合わせます。

元の時刻を残したまま、変換列を追加する

次が架空の入力CSVです。event_idは時刻から作らず、元データの識別子を使います。

event_id,paid_at_utc,amount_usd
E01,2025-11-02T03:30:00Z,100
E02,2025-11-02T05:30:00Z,200
E03,2025-11-02T06:30:00Z,300
E04,2025-11-03T04:30:00Z,400
E05,2025-11-03T05:00:00Z,500

PythonのzoneinfoはIANAの地域別タイムゾーンデータを利用します。UTCなど別のタイムゾーンから変換すると、切替前後の時差に応じた現地時刻を得られます。今回の変換はローカルのPythonと時刻データで計算しました。Python公式:zoneinfo(新しいタブで開く)

表は横にスクロールできます

IDUTCの元時刻現地日時とUTCオフセット集計日付USD
E012025-11-02 03:30Z2025-11-01 23:30 −04:002025-11-01100
E022025-11-02 05:30Z2025-11-02 01:30 −04:002025-11-02200
E032025-11-02 06:30Z2025-11-02 01:30 −05:002025-11-02300
E042025-11-03 04:30Z2025-11-02 23:30 −05:002025-11-02400
E052025-11-03 05:00Z2025-11-03 00:00 −05:002025-11-03500

E01はUTCでは11月2日ですが、今回の集計地域では11月1日です。E04は反対にUTCでは11月3日でも、現地では11月2日に入ります。元列を上書きせず、現地日時、地域名、集計日付を追加すれば、どの行が日付をまたいだか追えます。

同じ現地時刻を、重複レコードと決めない

E02とE03はどちらも現地の11月2日1時30分です。ただしUTCでは1時間違い、UTCオフセットも−04:00と−05:00で異なります。夏時間終了時の時計の戻りによるもので、時刻の見た目だけを理由に片方を削除しません。

この例はUTCの瞬間が元データにあるため、両者を区別できます。一方、「2025-11-02 01:30」という地域もオフセットもない値だけでは、どちらの瞬間かを一意に決められません。地域名が分かっても切替時の曖昧さが残る場合があります。記録元の仕様や追加情報を確認し、勝手に先の時刻・後の時刻へ寄せないでください。

Pythonにはこうした重なる現地時刻を区別するfoldの仕組みがありますが、値を選ぶ根拠が元データにない問題まで解決するわけではありません。時刻の解析失敗や地域不明の行は確認表へ残し、ゼロ件や対象外へ黙って置き換えません。

暦日をUTCの区間へ戻して境界を確認する

今回の地域の2025年11月2日は、次のUTC区間に対応します。開始を含み、終了を含まない区間です。

開始:2025-11-02T04:00:00Z 以上
終了:2025-11-03T05:00:00Z 未満
対象:E02、E03、E04
合計:200 + 300 + 400 = 900 USD

開始から終了までの経過時間は25時間です。現地の一日を常にUTCの24時間として切ると、この日に必要な範囲と一致しません。対象日の現地0時と翌日0時をそれぞれUTCへ変換してから、期間を確認します。

E05は終了境界と同じ05:00Zなので、11月2日の合計には入りません。23時59分59秒までの条件で切るより、翌日0時未満とする方が、小数秒のあるデータにも同じ境界を説明できます。

UTC集計と現地集計の違いを、全体合計でも照合する

同じ5件を二通りで集計すると、次のようになります。空欄の代わりの0は、この架空データ内で該当件数がないことを表すもので、実データの欠損補完ではありません。

表は横にスクロールできます

日付UTC日付で合計現地日付で合計
2025-11-010100
2025-11-02600900
2025-11-03900500
全5件合計1,5001,500

日別の差は、E01の100とE04の400が別の日へ移ったことで説明できます。全体合計が1,500で一致しても、日別の分類が正しい証拠にはなりません。反対に、日別合計だけを見ると、取引が消えたのか別の日へ移ったのか区別できません。ID別の変換表、日別集計、全体件数と金額を一緒に照合します。

実データで変換できない行があれば、集計対象と確認待ちを分けます。入力件数=集計した件数+確認待ち件数など、今回採用した処理区分で照合できるようにします。確認待ちの金額も、読み取れる範囲を別に記録します。

AIへは、日付の定義と確認表を指定する

このCSVの日別売上を確認してください。
元時刻paid_at_utcはUTC、集計地域はAmerica/New_Yorkです。
paid_at_utcを現地日時へ変換してから暦日を取得してください。
境界は現地0時以上、翌日0時未満です。
元IDと元時刻を保持し、地域名・UTCオフセット付き現地日時・集計日付を追加。
同じ現地時刻という理由だけでレコードを重複削除しないでください。
地域やオフセットが不明な時刻、解析できない行は推測せず確認待ちにしてください。
出力:ID別変換表、日別件数と合計、対象日のUTC境界、確認待ち一覧。
全体件数・金額も照合してください。今回の金額は全件USDです。
使用した計算方法とタイムゾーンデータの情報を示してください。
実行していない計算を、検証済みの結果として説明しないでください。
入力:[利用が認められたCSV]

日時を変換せず、タイムゾーン名だけを付け直す操作にも注意します。Pythonのastimezoneは同じ瞬間を保って別の地域へ変換するための方法です。単にtzinfoを置き換える操作とは役割が異なります。Python公式:datetime(新しいタブで開く)

地域の時差や夏時間の規則は変更されることがあります。IANAのデータベースもその変更を反映して更新されるため、計算環境のデータを記録します。公式サイトの最新版を見たことと、自分の環境がその版を使っていることは別です。IANA:Time Zones(新しいタブで開く)

CSV分析の道具選びは、CSVを分析するAIの選び方で扱います。日別の数値を受け渡すときは、集計地域、対象のイベント時刻、日付境界、確認待ち、元IDへの対応まで残すと、翌月の再集計でも同じ定義を使えます。

参考資料

公式資料の確認日:2026年10月20日。売上5件は架空例で、日時変換と合計をローカルで計算しました。実売上の定義、実システムの記録仕様、AIサービスの出力、表計算画面の表示は確認していません。