Usando o horário atual no UTC como valor padrão no PostgreSQL

172

Eu tenho uma coluna do TIMESTAMP WITHOUT TIME ZONEtipo e gostaria de ter esse padrão no horário atual no UTC. É fácil obter a hora atual no UTC:

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

Como está usando o registro de data e hora atual para uma coluna:

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)

Mas isso usa hora local. Tentar forçar isso ao UTC resulta em um erro de sintaxe:

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...
Wichert Akkerman
fonte

Respostas:

297

Uma função nem é necessária. Basta colocar parênteses em torno da expressão padrão:

create temporary table test(
    id int, 
    ts timestamp without time zone default (now() at time zone 'utc')
);
Daniel Vérité
fonte
2
Eu posso ver um funciton como now_utc () realmente brilha quando escrever consultas
misaxi
Isso funciona mesmo quando o tempo volta uma hora - now () retorna um carimbo de data / hora que conhece o deslocamento do UTC.
argila Lenhart
1
FWIW, executar esta consulta no PostgreSQL 11.5: ALTER TABLE testcase_result ADD COLUMN date_created TIMESTAMP WITHOUT TIME ZONE DEFAULT (NOW() AT TIME ZONE "UTC") NOT NULL;falha com: ERROR: column "UTC" does not exist. Verifique se 'utc'está tudo em minúsculas.
Codigo_dredd 22/11
2
Correção: A 'utc'sequência também deve ser entre aspas simples, não entre aspas duplas.
Codigo_dredd 22/11/19
56

Ainda outra solução:

timezone('utc', now())
martti
fonte
26

Envolva-o em uma função:

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()
);
Denis de Bernardy
fonte
16

A respeito

now()::timestamp

Se o seu outro registro de data e hora estiver sem fuso horário, esse elenco produzirá o tipo correspondente "registro de data e hora sem fuso horário" para o horário atual.

Eu gostaria de ler o que os outros pensam sobre essa opção, no entanto. Ainda não confio na minha compreensão desse material "com / sem" fuso horário.

EDIT: Adicionando o comentário de Michael Ekoka aqui, porque esclarece um ponto importante:

Embargo. A questão é gerar o carimbo de data e hora padrão no UTC para uma coluna de carimbo de data / hora que não armazena o fuso horário (talvez porque não seja necessário armazenar o fuso horário se você souber que todos os carimbos de hora compartilham o mesmo). O que sua solução faz é gerar um registro de data e hora local (que para a maioria das pessoas não será necessariamente definido como UTC) e armazená-lo como um registro de data e hora ingênuo (que não especifica seu fuso horário).

Risadinha
fonte
É um truque interessante, mas pode causar confusão, a menos que você esteja ciente desse comportamento. A resposta aceita é clara sobre a ação e o resultado desejado. Mesmo com a função, mas eu ficar longe de funções em DBs ....
Frank V
Na minha opção gera data e hora local no db
VelikiiNehochuha
Embargo. A questão é gerar o carimbo de data e hora padrão no UTC para uma coluna de carimbo de data / hora que não armazena o fuso horário (talvez porque não seja necessário armazenar o fuso horário se você souber que todos os carimbos de hora compartilham o mesmo). O que sua solução faz é gerar um registro de data e hora local (que para a maioria das pessoas não será necessariamente definido como UTC) e armazená-lo como um registro de data e hora ingênuo (que não especifica seu fuso horário).
Michael Ekoka 22/03/19
@MichaelEkoka Adicionei seu comentário na resposta - por favor, vá em frente e edite-o, se quiser. Você está explicando isso muito claramente. Obrigado!
Risadinha
Aviso : um registro de data e hora com fuso horário NÃO armazena o fuso horário, ao contrário do que se pensa. Veja o link abaixo e pesquise na página UTC. Na entrada, um registro de data e hora com fuso horário converte o valor recebido em utc e armazena esse valor SEM FUSO HORÁRIO OU INFORMAÇÕES DE COMPENSAÇÃO . Na saída, o valor utc armazenado é convertido em um horário local usando o fuso horário do cliente, se disponível. Esse tipo é sobre conversão de valor no momento da consulta. Você deve testar isso armazenando em um fuso horário e selecionando outro. postgresql.org/docs/11/datatype-datetime.html
Tom
7

Estas são 2 soluções equivalentes:

(no código a seguir, você deve substituir 'UTC'a zona e o carimbonow() de data e hora )

  1. timestamp AT TIME ZONE zone - em conformidade com o padrão SQL
  2. timezone(zone, timestamp) - indiscutivelmente mais legível

A função fuso horário (zona, registro de data e hora) é equivalente ao fuso horário da construção em conformidade com SQL AT TIME ZONE.


Explicação:

  • zona pode ser especificada como uma sequência de texto (por exemplo, 'UTC') ou como um intervalo (por exemplo, INTERVAL '-08:00') - aqui está uma lista de todos os fusos horários disponíveis
  • timestamp pode ser qualquer valor do tipo timestamp
  • now()retorna um valor do tipo timestamp (exatamente o que precisamos) com o fuso horário padrão do seu banco de dados anexado (por exemplo 2018-11-11T12:07:22.3+05:00).
  • timezone('UTC', now())transforma nosso horário atual (do tipo carimbo de data e hora com fuso horário ) no equivalente em fuso horário em UTC.
    Por exemplo, SELECT timestamp with time zone '2020-03-16 15:00:00-05' AT TIME ZONE 'UTC'retornará 2020-03-16T20:00:00Z.

Documentos: fuso horário ()

lakesare
fonte
1
Obrigado por resumir essas coisas. Eu usei a versão em minúscula at timezone 'utc'e isso não funcionou com a minha configuração do PostgreSQL. Problema resolvido com letras maiúsculas
Geradlus_RU 31/08/19
2

A função já existe: fuso horário ('UTC' :: text, now ())

user10259440
fonte