【Power Query】時刻が9時間ズレる原因とタイムゾーン変換

【Power Query】時刻が9時間ズレる原因とタイムゾーン変換のアイキャッチ Power Query

入力フォームの回答を、Googleフォーム→スプレッドシート→GASのJSON API→Power Queryの経路で取り込みました。このとき、時刻が日本時間より9時間ズレていました。値を見て、「世界標準時か」と気づきました。

この記事では、Power Queryのタイムゾーン変換(DateTimeZone.SwitchZone)と、時刻を突合のキーにしたときの落とし穴を整理します。

想定読者

外部から時刻の文字列を取り込む方、時刻をキーに別の表と突合したい方が対象です。

困った場面:時刻が9時間ズレて届く

取り込んだ時刻は文字列で、末尾に Z が付いていました(例:2026-10-07T03:31:00.000Z)。日本時間より9時間前の値です。Power Queryで日本時間に変換できるので、変換そのものにはさほど困りませんでした。

失敗したのは、この時刻を突合のキーにしたことです。記録側に、記録時刻ではなく処理時間を入れていました。意味の違う時刻を比べていたので、変換しても一致しません。そこで、取り込み時に連番を振り、連番で紐付ける形に変えました。

なお、JSONに変換するときにこの形になるようですが、原因は調べていません。Googleフォーム自体の仕様かどうかも、確認していません。

解決コード:SwitchZoneでJSTにそろえる

let
  Src = #table({"Ts"}, {{"2026-10-07T03:31:00.000Z"}, {"2026-10-07T04:05:30.000Z"}, {"2026-10-07T05:00:00.000Z"}}),
  Utc = Table.AddColumn(Src, "UtcAsIs",
    each DateTimeZone.RemoveZone(DateTimeZone.FromText([Ts])),
    type datetime),
  Jst = Table.AddColumn(Utc, "Jst",
    each DateTimeZone.RemoveZone(
      DateTimeZone.SwitchZone(DateTimeZone.FromText([Ts]), 9)),
    type datetime)
in
  Jst

結果は次の表です。Ts が元の文字列、UtcAsIs がUTCのままの日時、Jst が日本時間に変換した日時です。

Power Queryの結果表。Z付きの文字列(Ts列)、UTCのままの日時(UtcAsIs列)、JSTに変換した日時(Jst列)を3行で並べている。
再現用の最小コードの実行結果

解説:FromText→SwitchZone→RemoveZone

  1. DateTimeZone.FromText で、文字列をタイムゾーン付きの日時にします。Z は、ゾーン0として読まれました。
  2. DateTimeZone.SwitchZone(…, 9) で、+9時間のゾーンに切り替えます。03:31 が 12:31 になり、差は9時間でした。
  3. DateTimeZone.RemoveZone で、ゾーン情報を外します。

文字列のままでは、ただのテキストなので変換されません。日付や時刻が数字で扱われる仕組みは、【Excel】日付が数字になる仕組みとVBA・PQでの扱いで説明しています。

関数の仕様は、Microsoft LearnのDateTimeZone.SwitchZoneのページにあります。

同じ文字列を DateTime.FromText で読むと、今回のPCでは 12:31:00 になりました。PCの時刻に自動で変換されたように見えます。そのため、ズレに気づきにくくなります。今回のPCのタイムゾーンはUTC+9です。他のタイムゾーンのPCは未検証です。

検証環境は、Excel 16.0(Windows)です。他のバージョンとMac版は未検証です。

よくある失敗

  1. 変換しないまま突合する。手元のサンプル3行では、UTCのままだと一致が0件、JSTにそろえると3件でした。
  2. 比べている時刻の意味が違う。今回の私の失敗です。変換より先に、何の時刻かを確認します。
  3. DateTime.FromText の結果を、そのまま信じる。PCのタイムゾーンで結果が変わる可能性があります。

応用例:時刻ではなく連番で紐付ける

入力フォームでは、1人が複数回送信することがあります。名前の完全一致では足りませんでした。手元のサンプルで、名前がAの行が2つずつある3行の表同士を名前で結合すると、5行になりました。

取り込み時に連番(Table.AddIndexColumn)を振り、連番で紐付けたところ、1対1になりました。ただし、両方の表の並びがそろっていることが前提です。片方の並びが逆だと、組み合わせがずれます。フォームの回答が入るスプレッドシートは触らない運用で、並びを保っています。

キーの型がそろっていないと結合できない点は、【Power Query】キーの型がバラバラで結合できない時の対処法で扱っています。

同じJSONで、数値の項目が文字列と数値の両方で届く場合は、【Power Query】JSONの型ゆれ|文字列と数値の混在を吸収するを参照してください。

同じ名前が複数人にあたって行が増える場合の検知は、【Power Query】結合で行が増える原因と重複の検知方法で扱っています。

まとめ

時刻の文字列は、FromText→SwitchZone→RemoveZone でJSTにそろえます。突合のキーにするなら、その時刻が何の時刻かを先に確認します。時刻で突合できないときは、連番で紐付けます。並びがそろっていることが前提です。

コメント

タイトルとURLをコピーしました