タイムゾーン
Apache Supersetには、4つの異なるタイムゾーンコンポーネントが関連付けられています。
- 基盤となるデータがエンコードされているタイムゾーン。
- データベースエンジンのタイムゾーン。
- Apache Supersetバックエンドのタイムゾーン。
- Apache Supersetクライアントのタイムゾーン。
時間フィールド(`DATETIME`、`TIME`、`TIMESTAMP`など)にタイムゾーンが明示的に定義されていない場合、コンポーネントの基盤となるタイムゾーンがデフォルトで使用されます。
Apache Supersetは、データの取り込み方法(1)やクライアントのタイムゾーン(4)を制御できないため、問題をある程度扱いやすくするために、一貫性という観点から、(2)と(3)の両方を同じタイムゾーンで設定することを強く推奨します。明示的なタイムスタンプのない時間フィールドが誤ったタイムゾーンに強制的に変換されないように、UTCを優先することをお勧めします。実際、Apache Supersetは現在、タイムスタンプがUTCであるという暗黙の前提に基づいており、(3)をUTC以外のタイムゾーンに設定すると問題が発生する可能性があります。
データの一貫性を維持するために(クライアントのタイムゾーンに関係なく)、Apache Supersetバックエンドは、クライアントに送信されるタイムスタンプに、明示的な(またはエポック時間のように、常にUTCを参照しているため半明示的な)タイムゾーンがエンコードされていることを保証しようとします。
しかし、課題は、Apache Supersetがサポートするデータベースエンジンの種類と、それらのPython Database API (DB-API)実装間のさまざまな不整合、そしてPandasを使用してSQLをDataFrameに読み込む前にJSONにシリアライズするという事実から生じます。残念ながら、PandasはDB-APIのtype_codeを無視し、デフォルトでDB-APIによって返される基盤となるPython型に依存しています。現在、サポートされているデータベースエンジンのサブセットのみがPandasで正しく動作し、つまり、明示的なタイムスタンプのないタイムスタンプがサーバーのタイムゾーンを使用してJSONにシリアライズされ、クライアントのタイムゾーンに関係なく、クライアントがタイムスタンプを一貫した方法で表示することが保証されます。
たとえば、MySQLとPrestoを比較すると、
import pandas as pd
from sqlalchemy import create_engine
pd.read_sql_query(
sql="SELECT TIMESTAMP('2022-01-01 00:00:00') AS ts",
con=create_engine("mysql://root@localhost:3360"),
).to_json()
pd.read_sql_query(
sql="SELECT TIMESTAMP '2022-01-01 00:00:00' AS ts",
con=create_engine("presto://localhost:8080"),
).to_json()
それぞれ`{"ts":{"0":1640995200000}}`(エポック時間の定義に従ってUTCタイムゾーンを示唆)と`{"ts":{"0":"2022-01-01 00:00:00.000"}}`(明示的なタイムゾーンなし)が出力され、JavaScriptで異なる処理が行われます。
new Date(1640995200000)
> Sat Jan 01 2022 13:00:00 GMT+1300 (New Zealand Daylight Time)
new Date("2022-01-01 00:00:00.000")
> Sat Jan 01 2022 00:00:00 GMT+1300 (New Zealand Daylight Time)