とある日、個人開発をしているととあるバグに遭遇しました。
それは
現在時刻(JST)を取得してDBにINSERTするとUTCで時刻がINSERTされてしまう
というものでした。
解消のために試したこと
- API側(Go)のロジック内の時間をlogで出力
→JSTになっている - DBのTZ設定を
SET timezone TO 'Asia/Tokyo';
で設定
→変化なし - ORM(gorm)の設定見直し
→変化なし
なんで直らんねん!!!!!!!!!
と思って2.3日悪戦苦闘してました。
解決方法
DBのカラムの型をtimestamp
からtimestamptz(タイムゾーンあり)
に修正したらうまくいった
そもそも
そもそもSupabaseのカラム設定のところにtimestampで大丈夫???timestampzの方がおすすめだよ!!って懇切丁寧に書いてありました。
PostgreSQLのtimestamp
とtimestamptz
SupabaseはバックエンドにPostgreSQLを使用しており、PostgreSQLのデータ型に関する知識が不足してました。
PostgreSQLでは、時間を保存するために主に次の2つのデータ型があります
timestamp(タイムスタンプ)
この型はタイムゾーン情報を保持せず、単純に 「日付と時刻」の情報のみ を格納します。
タイムゾーンに関係なくそのまま保存されるため、取得した時刻がどのタイムゾーンを基準にしているかはデータからは分かりません。
timestamptz(タイムゾーン付きタイムスタンプ)
この型はタイムゾーンの情報を保持するため、格納された時間は常にUTCに変換されます。
クエリで時刻を取得すると、自動的にクライアントのタイムゾーンに応じて変換された結果を返します。つまり、異なるタイムゾーン間で一貫した時刻データを扱うことが可能です。
型名 | 保存されるデータ | タイムゾーン対応 | 保存時の変換 | 取得時の変換 |
---|---|---|---|---|
timestamp | 日付と時刻のみ | × | なし | なし |
timestamptz | 日付と時刻 + タイムゾーン情報 | ○ | UTCに変換される | クライアントのタイムゾーンに変換 |
参考文献