⭐
PySparkにおける日付時刻とTime Zone
概要
PySparkで日付時刻を扱う際の注意点
- 日付時刻型にはTimestampTypeとTimestampNTZTypeがある。
- Sparkセッションのタイムゾーン設定が挙動に影響するため明示的に設定した方がよい。
- 日付時刻文字列は意図しない変換を避けるためタイムゾーン情報をつけた方がよい。
- Pandasとの変換では意図しない変換を避けるためタイムゾーン情報をつけた方がよい。
- 公式ドキュメントにある程度記述がありますが、undocumentedな挙動も多いです。
2種類の日付時刻型
- TimestampType
- Sparkセッションのタイムゾーン設定 (
spark.sql.session.timeZone
) の影響を受けます。
- Sparkセッションのタイムゾーン設定 (
- TimestampNTZType
- タイムゾーン情報を持たないため、Sparkセッションのタイムゾーン設定の影響を受けません。
spark.sql.session.timeZone
)
Sparkセッションのタイムゾーン設定 (- この設定は以下の挙動に影響します。
- TimestampTypeの値を文字列として表示する際のタイムゾーン。
- タイムゾーン情報を含まない文字列(例: "2025-04-08 18:00:00")を TimestampType に変換する際の解釈。セッションタイムゾーンの時刻として解釈されます。
- current_timestamp() や now() といった現在時刻を返す関数の結果のタイムゾーン。
- hour(), minute(), date_format() など、TimestampType から日付/時刻要素を抽出する関数の結果。
- Spark DataFrame を Pandas DataFrame や Arrow Table に変換する際の TimestampType の扱い(UTCに正規化される際の基準タイムゾーンとして使用されます)。
- デフォルトはJVMのタイムゾーンです。
- 明示的に設定しておくとよいです。
spark.conf.set("spark.sql.session.timeZone", "Asia/Tokyo")
- 設定の確認
spark.conf.get("spark.sql.session.timeZone")
- 分散環境では各ノードの設定が異なる可能性があるため、理想的にはすべてのノードで明示的に設定しておいた方がよいようです。
文字列との変換
- タイムゾーン情報付き文字列
-
"2025-04-08T18:00:00+09:00"
のようなISO 8601形式の文字列をTimestampTypeにキャストする場合、文字列内のタイムゾーン情報が優先され、正しくUTCに変換されて格納されます。セッションタイムゾーン設定の影響は受けません。
-
- タイムゾーン情報なし文字列
-
"2025-04-08 18:00:00"
のような文字列を TimestampType にキャストする場合、セッションタイムゾーンの時刻として解釈されます。
-
- TimestampNTZTypeへのキャストでは、タイムゾーン情報は無視され、文字列の時刻がそのまま解釈されます。
- 意図しない変換を避けるためにタイムゾーン情報をつけた方がよいです。
Pandasとの変換
- PySpark → Pandas (
toPandas()
、pandas_udf
呼び出し)- PySparkのTimestampTypeはセッションタイムゾーンに従ってローカル時刻に変換され、Pandasのdatetime64[ns]に変わります。
- Pandas → PySpark (
createDataFrame()
、pandas_udf
の返り値)- datetime64[ns]が渡されるとUTCとして解釈されます。
- datetime64[ns, tz]はUTCに変換してからPySparkに渡されます。
- 意図しない変換を避けるためにタイムゾーン情報をつけた方がよいです。
まとめ
- Sparkセッションのタイムゾーン設定を明示的に設定した方がよい。
- 文字列でもPandasでもタイムゾーン情報をつけた方がよい。
Discussion