web-dev-qa-db-ja.com

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

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...
132

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

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

さらに別の解決策:

timezone('utc', now())
27
martti

関数でラップします。

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()
);
24

どう?

now()::timestamp

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

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

編集:Michael Ekokaのコメントをここに追加します。重要な点を明確にするためです。

警告。問題は、タイムゾーンを格納しないタイムスタンプ列のUTCでのデフォルトのタイムスタンプの生成に関するものです(すべてのタイムスタンプが同じであることがわかっている場合は、タイムゾーンを格納する必要がないためです)。解決策は、ローカルタイムスタンプ(ほとんどの人にとっては必ずしもUTCに設定されるとは限りません)を生成し、単純なタイムスタンプ(タイムゾーンを指定しないタイムスタンプ)として保存することです。

15
Risadinha

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

(次のコードでは、 zone 'UTC'に、 timestamp now()に置き換える必要があります)

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

関数timezone(zone、timestamp)は、SQL準拠のコンストラクトtimestamp AT TIME ZONE zoneと同等です。


説明:

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

ドキュメント: timezone()

2
lakesare

関数は既に存在します:timezone( 'UTC' :: text、now())

1
user10259440