web-dev-qa-db-ja.com

now():: timestamp関数を使用して保存された時間は誤った値を保存します

PGAdminでPostgreSQL 11データベースにAWS RDSを使用しています。 now()::timestampを使用してすべての行の作成日を保存し、タイムゾーンなしで日付と時刻を保存します。問題は、保存された時間が私が望む値ではないことです(UTC+05:30)。

RDSでパラメーターtimezoneUTCとして設定すると、保存される時刻はインドの時刻より5:30時間遅れますが、UTC + 05:30を設定すると、11時間遅れて保存されるか、さらに1時間、これはランダムな行でランダムに発生します。他に何も変更していません。このtimezoneパラメータだけです。

私はたくさん検索しましたが、同様の答えは見つかりませんでした。

2
Lalit Fauzdar

tl; dr

  • データ型TIMESTAMP WITHOUT TIME ZONEの代わりに、データ型TIMESTAMP WITH TIME ZONEの列を定義します。
  • PgAdmin内のセッションのデフォルトのタイムゾーンを [〜#〜] utc [〜#〜] に設定します。
  • 取得したUTC値をSQLの特定のタイムゾーンに調整するには、AT TIME ZONE 'Asia/Kolkata'を呼び出します。 (しかし、そのゾーン調整はSQLではなくアプリケーションコードに任せた方が良いです。)

TIMESTAMP WITHOUT TIME ZONE

タイムゾーンなしで日付と時刻を保存します。

列を定義するときに間違ったデータ型を使用しています。

TIMESTAMP WITHOUT TIME ZONE データ型は、モーメントを表すことはできません

このタイプは、意図的にタイムゾーンのコンテキストまたはUTCからのオフセットを欠いています。したがって、来年の1月23日の正午など、日付と時刻があります。しかし、東京の正午、フランスのトゥールーズの正午、米国のトレドオハイオの正午のどれを意味するのかは、数時間おきにまったく異なります。

入力とともに渡されるタイムゾーンまたはオフセット情報は、TIMESTAMP WITHOUT TIME ZONEタイプの列に到達すると無視されます。

TIMESTAMP WITH TIME ZONE

TIMESTAMP WITH TIME ZONE タイプは、タイムライン上の特定のポイントである瞬間を追跡できます。

日付と時刻とともに渡されるタイムゾーンまたはオフセット情報は、UTCに調整するために使用されます。その後、ゾーン/オフセットは破棄されます。したがって、元のゾーン/オフセットを気にする場合は、それを明示的に追加の列に格納する必要があります。

TIMESTAMP WITH TIME ZONE値を取得する場合、値は常にUTC(ゼロ時分秒のオフセット)になります。ただし、デフォルトのタイムゾーンを挿入するアンチ機能または取得した値にオフセットするツール、ミドルウェア、またはドライバーに注意してください。 実際にPostgresが常にデータタイプTIMESTAMP WITH TIME ZONEのUTC 値に格納するときに、このゾーン/オフセットが格納されているように見せかけます。

PgAdmin は、この残念なアンチ機能を備えたツールの1つです。セッションのデフォルトゾーンを常にUTCに設定して、取得した値が保存されたときにそれを確認することをお勧めします。

タイムゾーンに合わせる

UTCでプログラマーとして考え、働く方法を学ぶことをお勧めします。プログラミングにおけるほとんどのビジネスロジックはUTCである必要があります。ユーザーへの提示またはビジネスロジックが要求する場所でのみタイムゾーンに調整します。つまり、ほとんどの場合、SQLおよびデータベース管理ツールではなく、アプリコードでのみタイムゾーンに調整する必要があります。

AT TIME ZONE関数

ただし、SQLを使用してタイムゾーンに調整する場合は、 AT TIME ZONE 関数を使用します。

UTCの5時間半前のオフセット+05:30について説明しました。 インドでの時間 を意味していると思います。特定のオフセットではなく、常にリアルタイムゾーン名を優先します。政治家は、管轄区域で使用されるオフセットを頻繁に変更します。そのため、オフセットをハードコーディングすると、誤った結果が生じる可能性があります。

Postgresインストールの tzdata ファイルを最新の状態に保ち、 let Postgresがその特定の瞬間の名前付きタイムゾーンに適切なオフセットを決定します。

… AT TIME ZONE 'Asia/Kolkata' …

さまざまな日時データ型

私がJava=プログラマーのために作成したこのチャートも、SQL標準で定義されているさまざまなデータ型をよりよく理解するために、ここで役立つかもしれません。

Table of date-time types in Java (both legacy and modern) and in standard SQL

9
Basil Bourque

これをデフォルト値として使用する必要があると思います。

current_timestamp AT TIME ZONE '-05:30'

次に、PostgreSQLは現在の時点を取得し、その時点でインドに表示されるタイムスタンプにフォーマットします。

1
Laurenz Albe