PostgreSQLのデフォルト値としてUTCの現在時刻を使用する


172

TIMESTAMP WITHOUT TIME ZONEタイプの列があり、そのデフォルトをUTCの現在時刻にしたいと考えています。UTCで現在の時刻を取得するのは簡単です。

postgres=# select now() at time zone 'utc';
          timezone          
----------------------------
 2013-05-17 12:52:51.337466
(1 row)

列の現在のタイムスタンプをそのまま使用:

postgres=# create temporary table test(id int, ts timestamp without time zone default current_timestamp);
CREATE TABLE
postgres=# insert into test values (1) returning ts;
             ts             
----------------------------
 2013-05-17 14:54:33.072725
(1 row)

しかし、それは現地時間を使用します。これをUTCに強制しようとすると、構文エラーが発生します。

postgres=# create temporary table test(id int, ts timestamp without time zone default now() at time zone 'utc');
ERROR:  syntax error at or near "at"
LINE 1: ...int, ts timestamp without time zone default now() at time zo...

回答:


297

関数も必要ありません。デフォルトの式を括弧で囲むだけです:

create temporary table test(
    id int, 
    ts timestamp without time zone default (now() at time zone 'utc')
);

2
クエリを作成するときに、now_utc()のような関数が本当に輝くことがわかります
misaxi

これは、時間が1時間戻ったときにも機能します-now()はUTCからのオフセットを知っているタイムスタンプを返します。
クレイレンハート2016

1
FWIW、PostgreSQL 11.5でこのクエリを実行すると、次のALTER TABLE testcase_result ADD COLUMN date_created TIMESTAMP WITHOUT TIME ZONE DEFAULT (NOW() AT TIME ZONE "UTC") NOT NULL;エラーで失敗しますERROR: column "UTC" does not existすべて小文字であることを確認してください'utc'
code_dredd

2
修正:'utc'文字列も二重引用符ではなく、単一引用符で囲む必要があります。
code_dredd


26

それを関数にラップします:

create function now_utc() returns timestamp as $$
  select now() at time zone 'utc';
$$ language sql;

create temporary table test(
  id int,
  ts timestamp without time zone default now_utc()
);

16

どうですか

now()::timestamp

他のタイムスタンプにタイムゾーンがない場合、このキャストは現在の時刻に一致するタイプ「タイムゾーンなしのタイムスタンプ」を生成します。

しかし、他の人がそのオプションについてどう思うかを読みたいと思います。私は、この「タイムゾーンの有無」に関する私の理解をまだ信頼していません。

編集:重要なポイントを明確にするため、ここにマイケル・エコカのコメントを追加します:

警告。問題は、たまたまタイムゾーンを格納しないタイムスタンプ列のUTCでデフォルトのタイムスタンプを生成することです(おそらく、すべてのタイムスタンプが同じものを共有していることがわかっている場合はタイムゾーンを格納する必要がないためです)。ソリューションが行うことは、ローカルタイムスタンプ(ほとんどの場合、UTCに設定されているとは限りません)を生成し、それを単純なタイムスタンプ(タイムゾーンを指定しないタイムスタンプ)として保存することです。


これは興味深いトリックですが、この動作を認識していないと混乱を招く可能性があります。受け入れられた答えは、望ましい行動と結果について非常に明確です。関数と同じですが、DBの関数には近づきません...
Frank V

私のオプションでは、ローカルの日付時刻をdbに生成します
VelikiiNehochuha 2018年

警告。問題は、たまたまタイムゾーンを格納しないタイムスタンプ列のUTCデフォルトのタイムスタンプを生成することです(おそらく、すべてのタイムスタンプが同じものを共有していることがわかっている場合はタイムゾーンを格納する必要がないためです)。ソリューションが行うことは、ローカルタイムスタンプ(ほとんどの場合、必ずしもUTCに設定されているわけではない)を生成し、それを単純なタイムスタンプ(タイムゾーンを指定しないもの)として格納することです。
Michael Ekoka

@MichaelEkoka回答にコメントを追加しました-必要に応じて編集してください。あなたはそれを非常に明確に説明しています。ありがとう!
リサディーニャ

警告:タイムゾーンフィールドを含むタイムスタンプは、妥当な想定に反してタイムゾーンを格納しません。以下のリンクを参照して、ページでUTCを検索してください。入力時に、タイムゾーン付きのタイムスタンプは、入力値をutcに変換し、その値をWITH NO TIME ZONE OR OFFSET INFORMATIONで保存します。出力では、格納されているutc値は、クライアントのタイムゾーン(使用可能な場合)を使用して現地時間に変換されます。このタイプはすべて、クエリ時の値変換に関するものです。これをテストするには、あるタイムゾーンから保存し、別のタイムゾーンから選択する必要があります。postgresql.org/docs/11/datatype-datetime.html
Tom

7

これらは2つの同等のソリューションです。

(次のコードでは、あなたは置き換えてください'UTC'のためのゾーンnow()のためのタイムスタンプ

  1. timestamp AT TIME ZONE zone -SQL標準に準拠
  2. timezone(zone, timestamp) -間違いなくもっと読みやすい

関数timezone(zone、timestamp)は、SQL準拠の構成要素timestamp AT TIME ZONEゾーンと同等です。


説明:

  • ゾーンは、テキスト文字列(例:)'UTC'または間隔(例:)のいずれかとして指定できます。これINTERVAL '-08:00'は、使用可能なすべてのタイムゾーンのリストです。
  • タイムスタンプは、型の任意の値にすることができ、タイムスタンプ
  • now()データベースのデフォルトのタイムゾーンが付加されたタイムスタンプ(必要なものだけ)の値を返します(例:)2018-11-11T12:07:22.3+05:00
  • timezone('UTC', now())現在の時刻(タイムスタンプ付きのタイムスタンプ型)を、のタイムゾーンなしの同等のものに変換しUTCます。
    たとえば、SELECT timestamp with time zone '2020-03-16 15:00:00-05' AT TIME ZONE 'UTC'戻り2020-03-16T20:00:00Zます。

ドキュメント:timezone()


1
これらをまとめてくれてありがとう。私は小文字バージョンを使用at timezone 'utc'しましたが、私のPostgreSQLセットアップでは機能しません。大文字の使用による問題の解決
Geradlus_RU

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.