PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Preservar o fuso horário no tipo timestamptz do PostgreSQL


Como você já descobriu, o fuso horário não é salvo com os tipos de data/hora do Postgres, nem mesmo com timestamptz . Seu papel é apenas um modificador de entrada ou um decorador de saída, respectivamente. Apenas o valor (o ponto no tempo) é salvo. Amplos detalhes nesta resposta relacionada:
  • Ignorando completamente os fusos horários no Rails e no PostgreSQL

Portanto, se você quiser preservar essa parte da string de entrada, precisará extraí-la da string e salvá-la você mesmo. Eu usaria uma tabela como:
CREATE TABLE tstz
 ...
 , ts timestamp    -- without time zone
 , tz text
)

tz , sendo text , pode conter um deslocamento numérico bem como uma abreviatura de fuso horário , ou um fuso horário nome .

A dificuldade é extrair a parte do fuso horário de acordo com todas as várias regras que o analisador segue e de uma maneira que não seja quebrada facilmente. Em vez de preparar seu próprio procedimento, faça o analisador fazer o trabalho . Considere esta demonstração:
WITH ts_literals (tstz) AS (
   VALUES ('2013-11-28 23:09:11.761166+03'::text)
         ,('2013-11-28 23:09:11.761166 CET')
         ,('2013-11-28 23:09:11.761166 America/New_York')
   )
SELECT tstz
      ,tstz::timestamp AS ts
      ,right(tstz, -1 * length(tstz::timestamp::text)) AS tz
FROM   ts_literals;

SQL Fiddle.

Funciona com ou sem um T entre data e hora. A lógica chave está aqui:
right(tstz, -1 * length(tstz::timestamp::text)) AS tz

Pegue o que resta de uma string de carimbo de data/hora depois de cortar o comprimento do que o analisador identificou como componente de data/hora. Isso depende da entrada ser, como você afirmou:

strings ISO8601 validadas