🌴

[Redshift]勝手にサマータイム?

2023/04/17に公開

RedshiftでCONVERT_TIMEZONE関数を用いてUTC(協定世界時)から日本時間へ変換する処理を実装しています。

ある日、ユーザーからの問い合わせをきっかけに、UTCから日本時間へ正しく変換されていないことが発覚しました。

UTC+10

CONVERT_TIMEZONEの構文は下記の通りです。

CONVERT_TIMEZONE( ['source_timezone',] 'target_timezone', 'timestamp')

これを参考に、UTCのtimestampカラムを日本時間へ変換するべく、下記のような使い方をしていました。

SELECT CONVERT_TIMEZONE('UTC', 'Asia/Tokyo', 'timestamp') FROM hogehoge;

日本時間はUTC+9のため、UTCから9時間進んだ値が出力されたらOKです。
しかし、なぜか10時間進んだ値が出力されていたのです…。

サマータイム適用説

公式ドキュメントを改めて確認すると、気になる記述が…

タイムゾーン名の使用
タイムゾーン名を使用してタイムゾーンを指定する場合、CONVERT_TIMEZONE は自動的に夏時間 (DST)、または 'timestamp' によって指定される日付と時刻で有効なその他の現地の季節の慣習 (サマータイム、標準時、冬時間) を調整します。例えば、'Europe/London' は冬季は UTC を表し、夏季は 1 時間を追加します。

タイムゾーンの略名の使用
タイムゾーンの略名は、UTC からの固定オフセットを表します。タイムゾーンの略名を使用してタイムゾーンを指定する場合、CONVERT_TIMEZONE は UTC からの固定オフセットを使用し、現地の季節の慣習を調整しません。

サマータイムが導入されていない日本は無関係だと思っていたのですが、もしやと思い、タイムゾーン名(Asia/Tokyo)をタイムゾーンの略名(JST)に修正してみました。

SELECT CONVERT_TIMEZONE('UTC', 'JST', 'timestamp') FROM hogehoge;

上記を実行すると…ビンゴでした!UTCから9時間進んだ値が出力されました。

つまり、元のクエリはサマータイムだと判定されてUTC+9(日本時間)+1(サマータイム)=10時間進んだ値が出力されていた可能性が高そうです。

深まる謎

日次でCONVERT_TIMEZONEを用いた処理を実行しているテーブルの過去データを確認してみました。
2023年4月13日(日本時間)実行分からUTC+10の値になっており、それ以前はUTC+9の値でした。

サマータイム適用国について軽く調査したのですが、2023年4月13日からサマータイムを適用している国は無さそうでして…謎です。

私の知らない間に日本はサマータイムを導入していたのかもしれません(?)

結論

RedshiftでCONVERT_TIMEZONE使用する際はタイムゾーンの略名を用いた方が安全です!

余談:Snowflakeでは

念のためSnowflakeでも確認してみました。
Snowflakeでも

SELECT CONVERT_TIMEZONE('UTC', 'Asia/Tokyo', 'timestamp') FROM hogehoge;

という書き方が可能ですが、問題なくUTC+9時間で変換されることを確認しました。

ちなみに、Snowflakeの公式ドキュメント

Snowflakeは、タイムゾーンの 略語 の大半を サポートしていません (例: PDT、 EST)。特定の略語は、いくつかの異なるタイムゾーンの1つを参照している可能性があるためです。たとえば、 CST は、北米の中部標準時(UTC-6)、キューバ標準時(UTC-5)、および中国標準時(UTC+8)を指す場合があります。

と記載があるように、タイムゾーンの略名を殆どサポートしていません。

Snowflakeでは下記のようにタイムゾーン名(Asia/Tokyo)をタイムゾーンの略名(JST)に変更して実行するとエラーになりますので、ご注意下さい。

SELECT CONVERT_TIMEZONE('UTC', 'JST', 'timestamp') FROM hogehoge; -- NG

RedshiftのクエリをSnowflakeに移行する際は気にする必要がありますね。

2023/06/02 追記

AWSからRedshiftについてのアップデートの通知がありました。
UTC+10に変換されるのはバグだったようです。
通知の文面は下記。

2023 年 4 月 6 日にデプロイされた 1.0.48805、1.0.48771 (CURRENT メンテナンストラック)、1.0.48766、1.0.48714 (TRAILING メンテナンストラック) のバージョンで、'Asia/Tokyo' のタイムゾーンに関連する問題が検出されました。

この問題は、デフォルトのタイムゾーンが UTC から 'Asia/Tokyo' に変更され、影響を受けるバージョンにアップグレードされたプロビジョニングされたクラスターに限定されます。CONVERT_TIMEZONE などの関数を使用することで 'Asia/Tokyo' のタイムゾーンを使用するワークロードにも影響を与える可能性があります。サーバーレスエンドポイントは影響を受けません。

問題は、'Asia/Tokyo' のタイムゾーンを含むクエリで期待されるオフセットが UTC+9 (JST) のところ、UTC+10 (JDT) のオフセットで時間値を処理した可能性があることです。特に、TIMETZ 型と TIMESTAMPTZ 型の値を含む計算では、最大 1 時間の差で誤った結果が生成される可能性があります。DATE/TIME/TIMESTAMP 型は影響を受けなかったことに注意してください。

影響を受ける可能性のある AP-NORTHEAST-1 リージョンの Amazon Redshift クラスターのリストは、「影響を受けるリソース」タブにあります。

修正をリリースしました。クラスターがアップグレードされ、影響を受けていないことを確認するために、都合の良いときにクラスターをそれぞれのトラックの最新バージョンにアップグレードするようお願いします。'Asia/Tokyo' のタイムゾーンでデータが処理されたテーブルを調べて、値が期待どおりであることを確認することをお勧めします。

余談:JDTって何?

↑の文面に UTC+10(JDT) と記載がありますが、タイムゾーンの略名にJDTなんてありましたっけ??そもそもJDTって何の略?と思い調べてみました。

どうやら Japan Daylight-saving Time の略で、GHQ支配下の日本に存在したサマータイムを指すらしいです。

日本にもサマータイムが存在した時期があったんですね…!勉強になりました。

【参考記事】
Linuxでのサマータイム - JDTの来襲
サマータイム"70年前の愚"を繰り返すな
<今日は何の日>5月2日(1948年)『日本で初の夏時間導入』

Discussion