8.5. Tipos de dados de data e hora #

8.5.1. Entrada de data e hora
8.5.2. Saída de data e hora
8.5.3. Zonas horárias
8.5.4. Entrada de intervalo
8.5.5. Saída de intervalo

O PostgreSQL aceita o conjunto completo de tipos de dados de data e hora do padrão SQL, mostrados na Tabela 8.9. As operações disponíveis nesses tipos de dados são descritas na Seção 9.9. As datas são contadas segundo o calendário gregoriano, mesmo em anos anteriores à introdução desse calendário (veja a Seção B.6 para obter mais informações).

Tabela 8.9. Tipos de dados de data e hora

NomeTamanho de armazenamentoDescriçãoMenor valorMaior valorResolução
timestamp [ (p) ] [ without time zone ]8 bytestanto data quanto hora (sem zona horária)4713 A.C.294276 D.C.1 microssegundo
timestamp [ (p) ] with time zone8 bytestanto data quanto hora, com zona horária4713 A.C.294276 D.C.1 microssegundo
date4 bytesdata (sem hora do dia)4713 A.C.5874897 D.C.1 dia
time [ (p) ] [ without time zone ]8 byteshora do dia (sem data)00:00:0024:00:001 microssegundo
time [ (p) ] with time zone12 byteshora do dia (sem data), com zona horária00:00:00+155924:00:00-15591 microssegundo
interval [ campos ] [ (p) ]16 bytesintervalo de tempo-178000000 anos178000000 anos1 microssegundo

Nota

O padrão SQL requer que quando estiver escrito apenas timestamp isto seja equivalente a timestamp without time zone, e o PostgreSQL respeita este comportamento. O tipo de dados timestamptz é aceito como abreviatura para o tipo de dados timestamp with time zone; esta é uma extensão do PostgreSQL.

Os tipos de dados time, timestamp e interval aceitam um valor de precisão opcional p, que especifica o número de dígitos fracionários presentes no campo de segundos. Por padrão, não há um limite explícito para a precisão. O intervalo permitido para p é de 0 a 6.

O tipo de dados interval possui uma opção adicional, que é a de restringir o conjunto de campos armazenados escrevendo uma dessas frases:

YEAR
MONTH
DAY
HOUR
MINUTE
SECOND
YEAR TO MONTH
DAY TO HOUR
DAY TO MINUTE
DAY TO SECOND
HOUR TO MINUTE
HOUR TO SECOND
MINUTE TO SECOND

Note que, se tanto campos quanto p forem especificados, então campos deve incluir SECOND, uma vez que a precisão se aplica apenas aos segundos.

O tipo de dados time with time zone é definido pelo padrão SQL, mas a definição exibe propriedades que levam a uma utilidade questionável. Geralmente, uma combinação de date, time, timestamp without time zone e timestamp with time zone deve fornecer uma gama completa de funcionalidades de data/hora requeridas por qualquer aplicação.

8.5.1. Entrada de data e hora #

A entrada de data e hora é aceita em praticamente qualquer formato razoável, incluindo ISO 8601, o formato compatível com o padrão SQL, o formato tradicional do POSTGRES, e outros. Para alguns formatos, a ordem de dia, mês e ano na entrada da data é ambíguo, e há suporte para especificar a ordem esperada destes campos. O parâmetro DateStyle deve ser configurado como MDY para selecionar a interpretação mês-dia-ano, como DMY para selecionar a interpretação dia-mês-ano, ou como YMD para selecionar a interpretação ano-mês-dia.

Exemplo 8.6. Exemplo do tradutor

Esta consulta mostra o valor do parâmetro DateStyle em uso, que neste caso é ISO 8601 (ano-mês-dia), seguido por DMY (dia/mês/ano).

SELECT name, setting, short_desc
    FROM pg_settings
    WHERE name='DateStyle';
   name    | setting  |                        short_desc
-----------+----------+-----------------------------------------------------------
 DateStyle | ISO, DMY | Define o formato de exibição para valores de data e hora.
(1 linha)

O PostgreSQL é mais flexível no modo de tratar a entrada de data/hora do que o padrão SQL requer. Veja o Apêndice B para obter as regras exatas de análise de entrada de data/hora e os campos de texto reconhecidos, incluindo meses, dias da semana e zonas horárias. [43]

Lembre-se de que qualquer entrada literal de data ou hora precisa ser colocada entre apóstrofos, como as cadeias de caracteres de texto. Veja a Seção 4.1.2.7 para obter mais informações. O padrão SQL requer a seguinte sintaxe

tipo_de_dados [ (p) ] 'valor'

onde p é uma especificação de precisão opcional, que fornece o número de dígitos fracionários no campo de segundos. A precisão pode ser especificada para os tipos de dados time, timestamp e interval, podendo estar no intervalo de 0 a 6. Se nenhuma precisão for especificada na especificação da constante, o padrão será a precisão do valor literal (mas não mais de 6 dígitos).

8.5.1.1. Datas #

A Tabela 8.10 mostra as entrada possíveis para o tipo de dados date.

Tabela 8.10. Entradas de data

ExemploDescrição
1999-01-08ISO 8601; 8 de janeiro de 1999 em qualquer modo (formato recomendado)
January 8, 19998 de janeiro de 1999, não ambíguo em qualquer modo de entrada em datestyle
1/8/19998 de janeiro de 1999 no modo MDY; 1º de agosto de 1999 no modo DMY
1/18/199918 de janeiro de 1999 no modo MDY; rejeitado nos outros modos
01/02/032 de janeiro de 2003 no modo MDY; 1º de fevereiro de 2003 no modo DMY; 3 de fevereiro de 2001 no modo YMD
1999-Jan-088 de janeiro de 1999 em qualquer modo
Jan-08-19998 de janeiro de 1999 em qualquer modo
08-Jan-19998 de janeiro de 1999 em qualquer modo
99-Jan-088 de janeiro de 1999 no modo YMD, rejeitado nos outros modos
08-Jan-998 de janeiro de 1999, exceto no modo YMD, onde é rejeitado
Jan-08-998 de janeiro de 1999, exceto no modo YMD, onde é rejeitado
19990108ISO 8601; 8 de janeiro de 1999 em qualquer modo
990108ISO 8601; 8 de janeiro de 1999 em qualquer modo
1999.0088 de janeiro de 1999; ano e dia do ano
J24511878 de janeiro de 1999; data juliana
January 8, 99 BC0099-01-08 BC, ano 99 antes de Cristo

8.5.1.2. Hora #

Os tipos de dados para hora do dia são time [ (p) ] without time zone e time [ (p) ] with time zone. time sozinho equivale a time without time zone.

A entrada válida para estes tipos de dados consiste em uma hora do dia seguida por uma zona horária opcional. (Veja a Tabela 8.11 e a Tabela 8.12.) Se for especificada uma zona horária na entrada para o tipo de dados time without time zone, ela será ignorada em silêncio. Também pode ser especificada uma data, mas ela será ignorada, exceto quando for usado um nome de zona horária que envolva uma regra de horário de verão como, por exemplo, America/New_York. Nesse caso é necessário especificar a data, para determinar se vai ser aplicado o horário padrão ou o horário de verão. O deslocamento de zona horária apropriado é registrado no valor de time with time zone e é mostrado da mesma forma como está armazenado; não é ajustado para a zona horária ativa.

Tabela 8.11. Entrada de hora

ExemploDescrição
04:05:06.789ISO 8601
04:05:06ISO 8601
04:05ISO 8601
040506ISO 8601
04:05 AMidêntico a 04:05; AM não afeta o valor
04:05 PMidêntico a 16:05; a hora entrada deve ser <= 12
04:05:06.789-8ISO 8601, com zona horária como deslocamento UTC
04:05:06-08:00ISO 8601, com zona horária como deslocamento UTC
04:05-08:00ISO 8601, com zona horária como deslocamento UTC
040506-08ISO 8601, com zona horária como deslocamento UTC
040506+0730ISO 8601, com hora fracionária de zona horária como deslocamento UTC
040506+07:30:00deslocamento UTC especificado em segundos (não permitido na ISO 8601)
04:05:06 PSTzona horária especificada por abreviatura
2003-04-12 04:05:06 America/New_Yorkzona horária especificada pelo nome completo

Tabela 8.12. Entada de zona horária

ExemploDescrição
PSTAbreviatura (Pacific Standard Time)
America/New_YorkNome completo da zona horária
PST8PDTespecificação de zona horária no estilo POSIX
-8:00:00deslocamento UTC para PST
-8:00deslocamento UTC para PST (formato estendido ISO 8601)
-800deslocamento UTC para PST (formato básico ISO 8601)
-8deslocamento UTC para PST (formato básico ISO 8601)
zuluAbreviatura militar para UTC
zForma curta para zulu (também na ISO 8601)

Veja a Seção 8.5.3 pata obter mais informações sobre como especificar as zonas horárias.

8.5.1.3. Carimbos de tempo #

A entrada válida para os tipos de dados de carimbo de tempo consiste na concatenação de uma data e uma hora, seguida por uma zona horária opcional, seguida por AD ou BC opcional. (Como alternativa, AD/BC pode aparecer antes da zona horária, mas esta não é a ordem preferida.) Assim

1999-01-08 04:05:06

e

1999-01-08 04:05:06 -8:00

são valores válidos que seguem o padrão ISO 8601. Além disso, o formato comum

January 8 04:05:06 1999 PST

também é aceito.

O padrão SQL diferencia os literais timestamp without time zone e timestamp with time zone pela presença do símbolo + ou - e a zona horária após a hora. Então, segundo o padrão,

TIMESTAMP '2004-10-19 10:23:54'

é timestamp without time zone, enquanto

TIMESTAMP '2004-10-19 10:23:54+02'

é timestamp with time zone. O PostgreSQL nunca examina o conteúdo de literal cadeia de caracteres antes de determinar o seu tipo de dados, portanto trata as duas formas acima como timestamp without time zone. Para garantir que o literal vai ser tratado como timestamp with time zone, o tipo de dados correto deve ser indicado explicitamente:

TIMESTAMP WITH TIME ZONE '2004-10-19 10:23:54+02'

Em um valor que tenha sido determinado como sendo timestamp without time zone, o PostgreSQL irá ignorar em silêncio qualquer indicação de zona horária. Ou seja, o valor resultante é derivado dos campos de data/hora no valor de entrada sem ser ajustado para a zona horária.

Para valores de `timestamp with time zone`, uma cadeia de caracteres de entrada que inclua uma zona horária explícita será convertida para UTC (Universal Coordinated Time) utilizando o deslocamento apropriado para esta zona horária. Se não for especificada uma zona horária na cadeia de caracteres de entrada, assume-se que a zona horária seja a indicada pelo parâmetro do sistema TimeZone , sendo convertido para UTC usando o deslocamento para a zona horária timezone. Em ambos os casos, o valor é armazenado internamente em UTC, e a zona horária originalmente declarada ou assumida não é mantida.

Quando um valor timestamp with time zone é mostrado, é sempre convertido de UTC para para a zona horária corrente de timezone, e mostrado como hora local nessa zona. Para ver a hora em outra zona horária, deve ser mudado o valor de timezone, ou usada a construção AT TIME ZONE. (veja a Seção 9.9.4).

As conversões entre timestamp without time zone e timestamp with time zone normalmente assumem que o valor de timestamp without time zone deve ser aceito ou mostrado como hora local de timezone. Uma zona horária diferente pode ser especificada para a conversão usando AT TIME ZONE.

8.5.1.4. Valores especiais #

O PostgreSQL aceita vários valores especiais de data/hora por conveniência, conforme mostrado na Tabela 8.13. Os valores infinity e -infinity têm uma representação especial dentro do sistema, e são mostrados sem alterações; mas os demais valores são apenas uma forma de notação abreviada, sendo convertidos para valores comuns de data/hora assim que são lidos. (Em particular, now e cadeias relacionadas são convertidas para valores específicos assim que são lidas.) Todos estes valores precisam ser colocados entre apóstrofos quando usados como constantes em comandos SQL.

Tabela 8.13. Entradas especiais de data e hora

Cadeia de entradaTipos de dados válidosDescrição
epochdate, timestamp1970-01-01 00:00:00+00 (hora zero do sistema Unix)
infinitydate, timestamp, intervalmais tarde que todos os outros carimbos de tempo
-infinitydate, timestamp, intervalmais cedo que todos os outros carimbos de tempo
nowdate, time, timestamphora de início da transação corrente
todaydate, timestampmeia-noite (00:00) de hoje
tomorrowdate, timestampmeia-noite (00:00) de amanhã
yesterdaydate, timestampmeia noite (00:00) de ontem
allballstime00:00:00.00 UTC

Também podem ser usadas as seguintes funções compatíveis com o padrão SQL no tipo de dados correspondente: CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP, LOCALTIME, LOCALTIMESTAMP. (Veja a Seção 9.9.5.) Note que estas são funções SQL e não são reconhecidas como cadeia de caracteres de entrada de dados (ou seja, não devem ser escritas entre apóstrofos).

Exemplo 8.7. Exemplo do tradutor

Neste exemplo são inseridos valores em um campo do tipo de dados timestamp with time zone usando entradas especiais e funções de data e hora e, em seguida, é realizada uma consulta para ver como são mostrados os que foram valores inseridos.

BEGIN;

CREATE TEMPORARY TABLE t (
    c1 TEXT,
    c2 TIMESTAMP WITH TIME ZONE
) ON COMMIT DROP;

INSERT INTO t VALUES
    ('epoch', 'epoch'),
    ('infinity', 'infinity'),
    ('-infinity', '-infinity'),
    ('now', 'now'),
    ('today', 'today'),
    ('tomorrow', 'tomorrow'),
    ('yesterday', 'yesterday'),
    ('LOCALTIMESTAMP', LOCALTIMESTAMP);

SELECT pg_sleep(2); -- dormir por 2 segundos

INSERT INTO t VALUES
    ('CURRENT_TIMESTAMP', CURRENT_TIMESTAMP);

SELECT * FROM t;
        c1         |              c2
-------------------+-------------------------------
 epoch             | 1969-12-31 21:00:00-03
 infinity          | infinity
 -infinity         | -infinity
 now               | 2026-01-16 10:13:56.262454-03
 today             | 2026-01-16 00:00:00-03
 tomorrow          | 2026-01-17 00:00:00-03
 yesterday         | 2026-01-15 00:00:00-03
 LOCALTIMESTAMP    | 2026-01-16 10:13:56.262454-03
 CURRENT_TIMESTAMP | 2026-01-16 10:13:56.262454-03
(9 linhas)
COMMIT;

Note que a data e a hora não mudam dentro da transação, é a data e hora da transação, e não a do comando INSERT.


Cuidado

Enquanto as cadeias de caracteres de entrada now, today, tomorrow e yesterday são boas para uso nos comandos SQL interativos, elas podem ter um comportamento surpreendente quando são salvas e executadas posteriormente como, por exemplo, em instruções preparadas, visões e definições de função. A cadeia de caracteres pode ser convertida em um valor de tempo específico, que continua sendo usado por muito tempo após estar desatualizado. Nesses contextos é melhor usar uma função SQL. Por exemplo, CURRENT_DATE + 1 é mais seguro que 'tomorrow'::date.

8.5.2. Saída de data e hora #

O formato de saída dos tipos de dados de data/hora pode ser definido como um destes quatro estilos: ISO 8601, SQL (Ingres), POSTGRES tradicional (formato date do Unix), ou German. O padrão é o formato ISO. (O padrão SQL requer o uso do formato ISO 8601. O nome do formato de saída SQL é um acidente histórico.) A Tabela 8.14 mostra um exemplo para cada estilo de saída. A saída dos tipos de dados date e time são geralmente apenas a parte da data ou da hora segundo os exemplos fornecidos. Entretanto, o estilo POSTGRES produz a saída de valores para apenas data no formato ISO. [44]

Tabela 8.14. Estilos de saída de data e hora

Especificação do estiloDescriçãoExemplo
ISOISO 8601, padrão SQL1997-12-17 07:37:16-08
SQLestilo tradicional12/17/1997 07:37:16.00 PST
Postgresestilo originalWed Dec 17 07:37:16 1997 PST
Germanestilo regional17.12.1997 07:37:16.00 PST

Nota

O padrão ISO 8601 especifica o uso da letra maiúscula T para separar a data da hora. O PostgreSQL aceita este formato na entrada, mas na saída usa espaço no lugar do T, conforme mostrado acima. Isso se dá para melhor legibilidade e consistência com o RFC 3339, assim como outros sistemas de banco de dados.

Nos estilos SQL e POSTGRES o dia aparece antes do mês, se tiver sido especificada a ordenação de campo DMY, caso contrário o mês aparece antes do dia. (Veja Seção 8.5.1 para saber como esta configuração também afeta a interpretação dos valores de entrada.) A Tabela 8.15 mostra exemplos.

Tabela 8.15. Convenções de ordem na data

Definição de datestyleOrdem de entradaExemplo de saída
SQL, DMYdia/mês/ano17/12/1997 15:37:16.00 CET
SQL, MDYmês/dia/ano12/17/1997 07:37:16.00 PST
Postgres, DMYdia/mês/anoWed 17 Dec 07:37:16 1997 PST

No estilo ISO, a zona horária é sempre mostrada como um deslocamento numérico com sinal em relação a UTC, com sinal positivo usado para zonas a leste de Greenwich. O deslocamento é mostrado como hh (somente horas) se for um número inteiro de horas, senão como hh:mm se for um número inteiro de minutos, senão como hh:mm:ss. (O terceiro caso não é possível com nenhum padrão de zona horária moderno, mas pode aparecer ao se trabalhar com carimbos de data/hora anteriores à adoção de zonas horárias padronizadas.) Nos outros estilos de data, a zona horária é mostrada como abreviatura alfabética, se isto for de uso comum na zona corrente. Caso contrário, aparece como um deslocamento numérico com sinal no formato ISO 8601 básico (hh ou hhmm). As abreviações alfabéticas exibidas nestes estilos são extraídas da entrada do banco de dados de zona horária da IANA atualmente selecionada pelo parâmetro de tempo de execução TimeZone; elas não são afetadas pela definição de timezone_abbreviations.

O estilo de data/hora pode ser selecionado pelo usuário usando o comando SET datestyle, mudando o parâmetro DateStyle no arquivo de configuração postgresql.conf, ou usando a variável de ambiente PGDATESTYLE no servidor, ou no cliente.

A função de formatação to_char (veja a Seção 9.8) também está disponível como uma forma mais flexível para formatar a saída de data/hora.

Exemplo 8.8. Exemplo do tradutor

Neste exemplo é entrada uma data com a zona horária UTC-8 (PST, Hora Padrão do Pacífico, Costa Oeste, EUA), que depois é mostrada em uma máquina configurada com a zona horária America/Sao_Paulo (UTC-3)

BEGIN;

CREATE TEMPORARY TABLE t (
    c TIMESTAMP WITH TIME ZONE
) ON COMMIT DROP;

INSERT INTO t VALUES ('1997-12-17 07:37:16-08');

SET datestyle = 'ISO';

SELECT * FROM t;
           c
------------------------
 1997-12-17 13:37:16-02
COMMIT;

Note que a data/hora foi convertida para UTC-2 devido ao Horário de Verão no Brasil em dezembro de 1997.


8.5.3. Zonas horárias #

As zonas horárias e as convenções de zona horária são influenciadas por decisões políticas, não apenas pela geometria da Terra. As zonas horárias em todo o mundo tornaram-se um pouco padronizadas durante os anos 1900, mas continuam propensas a mudanças arbitrárias, principalmente no que diz respeito às regras de horário de verão. O PostgreSQL usa o banco de dados de zona horária IANA (Olson) amplamente utilizado para obter informações sobre as regras históricas de zona horária. [45] Para horas no futuro, supõe-se que as últimas regras conhecidas para uma determinada zona horária continuarão a ser observadas indefinidamente no futuro.

O PostgreSQL se esforça para ser compatível com as definições do padrão SQL para uso típico. Entretanto, o padrão SQL tem uma mistura estranha de tipos de dados e recursos de data e hora. Dois problemas óbvios são:

  • Embora o tipo de dados date não possa ser associado a uma zona horária, o tipo de dados time pode. As zonas horárias no mundo real têm pouco significado, a menos que estejam associadas a uma data e a uma hora, porque o deslocamento pode variar ao longo do ano com os limites do horário de verão.

  • A zona horária padrão é especificada como um deslocamento numérico constante de UTC. Portanto, é impossível adaptar ao horário de verão ao fazer aritmética de data/hora através dos limites do DST (Daylight Saving Time [Horário de Verão]).

Para solucionar estas dificuldades, recomenda-se usar tipos de dados data/hora que contenham a data e a hora quando são usadas zonas horárias. Não é recomendado usar o tipo de dados time with time zone (embora seja aceito pelo PostgreSQL para aplicações legadas e para conformidade com o padrão SQL). O PostgreSQL assume a zona horária local para qualquer tipo de dados contendo apenas a data e a hora.

Todas as datas e horas com informação de zona horária são armazenadas internamente em UTC. Elas são convertidas para a hora local na zona especificada pelo parâmetro de configuração TimeZone antes de serem mostradas no cliente.

O PostgreSQL permite especificar as zonas horárias de três maneiras diferentes:

  • Um nome completo de zona horária como, por exemplo, Brazil/East. [46] Os nomes reconhecidos de zonas horárias estão listados na Seção 53.34. O PostgreSQL usa os dados de zona horária da IANA amplamente usados para esta finalidade, portanto os mesmos nomes de zona horária também são reconhecidos por outros softwares.

  • Uma abreviatura de zona horária como, por exemplo, PST. Tal especificação define apenas um deslocamento específico do UTC, em contraste com os nomes de zona horária completos, que também podem implicar em um conjunto de regras de transição de horário de verão. As abreviaturas reconhecidas estão listadas na Seção 53.33. Não é possível definir os parâmetros de configuração TimeZone ou log_timezone com uma abreviatura de zona horária, mas pode ser usada uma abreviatura nos valores de entrada de data/hora com o operador AT TIME ZONE.

  • Além dos nomes e abreviaturas de zonas horárias, o PostgreSQL aceita especificações de zona horária no estilo POSIX, conforme descrito na Seção B.5. Normalmente esta opção não é a preferida para ser usada como nome de zona horária, mas pode ser necessária se nenhuma entrada de zona horária da IANA adequada estiver disponível.

Em resumo, esta é a diferença entre abreviaturas e nomes completos: as abreviaturas representam um deslocamento UTC específico, enquanto muitos nomes completos implicam em uma regra de horário de verão local, portanto têm dois deslocamentos de UTC possíveis. Por exemplo, 2014-06-04 12:00 America/New_York representa meio-dia na hora local de Nova York, que para esta data em particular estava no horário de verão (Eastern Daylight Time = UTC-4). Portanto, 2014-06-04 12:00 EDT especifica este mesmo instante de hora. Mas 2014-06-04 12:00 EST especifica meio-dia no Horário Padrão da Costa Leste (Eastern Standard Time = UTC-5), independentemente do horário de verão estar em vigor nesta data ou não.

Nota

O sinal nas especificações de zona horária no estilo POSIX tem o significado oposto ao do sinal nos valores de data e hora ISO-8601. Por exemplo, a zona horária POSIX para 2014-06-04 12:00+04 seria UTC-4.

Para complicar as coisas, algumas jurisdições usaram a mesma abreviatura de zona horária para significar diferentes deslocamentos de UTC em horários diferentes; por exemplo, em Moscou MSK significa UTC+3 em alguns anos, e UTC+4 em outros. O PostgreSQL interpreta estas abreviaturas conforme o que elas significam (ou significaram mais recentemente) na data específica; mas como no exemplo de EST acima, esta não é necessariamente idêntica à hora civil nessa data.

Em todos os casos, os nomes e abreviaturas de zona horária são reconhecidos sem distinção entre letras maiúsculas e minúsculas. (Essa é uma mudança em relação às versões do PostgreSQL anteriores a 8.2, que faziam distinção entre letras maiúsculas e minúsculas em alguns contextos, enquanto em outros não.)

Nem os nomes das zonas horárias, nem as abreviaturas, estão codificados no servidor; estes são obtidos nos arquivos de configuração armazenados sob .../share/timezone/ e .../share/timezonesets/ do diretório de instalação (veja a Seção B.4).

O parâmetro de configuração TimeZone pode ser definido no arquivo postgresql.conf, ou de qualquer outra forma padrão descrita no Capítulo 19. Também existem algumas maneiras especiais para defini-lo:

  • O comando SQL SET TIME ZONE define a zona horária para a seção. Essa é uma ortografia alternativa para SET TIMEZONE TO com uma sintaxe mais compatível com a especificação do padrão SQL.

  • A variável de ambiente PGTZ é usada pela biblioteca libpq para enviar o comando SET TIME ZONE para o servidor na hora da conexão. (veja a Seção 32.15)

Exemplo 8.9. Zonas horárias para o Brasil

Embora existam algumas zonas horárias para o Brasil com o prefixo 'America/', como 'America/Sao_Paulo', também existem quatro com o prefixo 'Brazil/'. O seguinte exemplo lista estas quatro zonas horárias usando comandos do Linux e uma consulta à tabela do PostgreSQL.

$ # Linux Debian 12
$ timedatectl list-timezones | grep Brazil
Brazil/Acre
Brazil/DeNoronha
Brazil/East
Brazil/West
$ ls -l /usr/share/zoneinfo/Brazil/ | cut -c40-
Acre -> ../America/Rio_Branco
DeNoronha -> ../America/Noronha
East -> ../America/Sao_Paulo
West -> ../America/Manaus
-- PostgreSQL

SELECT * FROM pg_timezone_names
    WHERE name LIKE 'Brazil%'
    ORDER BY abbrev;
       name       | abbrev | utc_offset | is_dst
------------------+--------+------------+--------
 Brazil/DeNoronha | -02    | -02:00:00  | f
 Brazil/East      | -03    | -03:00:00  | f
 Brazil/West      | -04    | -04:00:00  | f
 Brazil/Acre      | -05    | -05:00:00  | f
(4 linhas)

8.5.4. Entrada de intervalo #

Os valores de interval podem ser escritos usando a seguinte sintaxe detalhada:

[@] quantidade unidade [quantidade unidade...] [direção]

onde quantidade é um número (possivelmente com sinal); unidade é microsecond, millisecond, second, minute, hour, day, week, month, year, decade, century, millennium, ou abreviaturas, ou plurais dessas unidades; direção pode ser ago ou estar vazia. O sinal (@) é um ruído opcional. As quantidades das diferentes unidades são adicionadas implicitamente com a contabilização de sinais apropriada. ago nega todos os campos. Essa sintaxe também será usada na saída de intervalo, se IntervalStyle estiver definido como postgres_verbose.

Quantidades de dias, horas, minutos e segundos podem ser especificadas sem marcações de unidades explícitas. Por exemplo, '1 12:59:10' é lido da mesma forma que '1 day 12 hours 59 min 10 sec'. Além disso, uma combinação de anos e meses pode ser especificada com um traço; por exemplo, '200-10' é lido da mesma forma que '200 years 10 months'. (Estas formas mais curtas são de fato as únicas permitidas pelo padrão SQL, sendo usadas na saída quando IntervalStyle é definido como sql_standard.)

Os valores de intervalo também podem ser escritos como intervalos de tempo ISO 8601, usando o formato com designadores da seção 4.4.3.2 do padrão, ou o formato alternativo da seção 4.4.3.3. O formato com designadores se parece com:

P quantidade unidade [ quantidade unidade ...] [ T [ quantidade unidade ...]]

A cadeia de caracteres deve começar com a letra P, podendo incluir a letra T que introduz as unidades da hora do dia. As abreviaturas disponíveis estão listadas na Tabela 8.16. As unidades podem ser omitidas, podendo ser especificadas em qualquer ordem, mas as unidades menores que um dia devem aparecer depois do T. Em particular, o significado de M depende se está antes ou depois do T.

Tabela 8.16. Abreviaturas das unidades de intervalo ISO 8601

AbreviaturaSignificado
YAnos
MMeses (na parte da data)
WSemanas
DDias
HHoras
MMinutos (na parte da hora)
SSegundos

No formato alternativo

P [ anos-meses-dias ] [ T horas:minutos:segundos ]

a cadeia de caracteres deve começar com a letra P, e o T separa a parte da data e da hora do intervalo. Os valores são fornecidos como números semelhantes às datas ISO 8601.

Ao escrever uma constante de intervalo com uma especificação de campos, ou quando atribuir uma cadeia de caracteres a uma coluna de intervalo definida com a especificação de campos, a interpretação das quantidades não marcadas depende de campos. Por exemplo, INTERVAL '1' YEAR é lido como 1 ano, enquanto INTERVAL '1' significa 1 segundo. Também, os valores de campo à direita do campo menos significativo permitido pela especificação de campos são descartados em silêncio. Por exemplo, escrever INTERVAL '1 day 2:03:04' HOUR TO MINUTE resulta na eliminação do campo de segundos, mas não no campo de dia.

Segundo o padrão SQL, todos os campos de um valor de intervalo devem ter o mesmo sinal, então o sinal menos à esquerda se aplica a todos os campos; por exemplo, o sinal menos no literal de intervalo '-1 2:03:04' se aplica tanto aos dias quanto às horas/minutos/segundos. O PostgreSQL permite que os campos tenham sinais diferentes e, tradicionalmente, trata cada campo na representação textual como tendo sinais independentes, portanto a parte de hora/minuto/segundo é considerada positiva nesse exemplo. Se IntervalStyle estiver definido como sql_standard, então o sinal à esquerda é considerado como sendo aplicado a todos os campos (mas apenas se não aparecer nenhum sinal adicional). De outra forma, a interpretação tradicional do PostgreSQL é usada. Para evitar ambiguidade, é recomendável anexar um sinal explícito a cada campo se algum campo for negativo.

Internamente, os valores de interval são armazenados como três campos de números inteiros: meses, dias e microssegundos. Estes campos são mantidos em separado porque o número de dias em um mês varia, e um dia pode ter 23 ou 25 horas se houver mudança para o horário de verão. Uma cadeia de caracteres de entrada para intervalo que utiliza outras unidades é normalizada para este formato e, em seguida, reconstruída de forma padronizada para a saída, por exemplo:

SELECT '2 years 15 months 100 weeks 99 hours 123456789 milliseconds'::interval;

               interval
---------------------------------------
 3 years 3 mons 700 days 133:17:36.789

Aqui, as semanas, entendidas como tendo 7 dias, foram mantidas em separado, enquanto as unidades de tempo menores e maiores foram combinadas e normalizadas.

Os valores dos campos de entrada podem conter partes fracionárias como, por exemplo, '1.5 weeks' ou '01:02:03.45'. Entretanto, como interval armazena internamente apenas campos de números inteiros, os valores fracionários devem ser convertidos em unidades menores. As partes fracionárias de unidades maiores que meses são arredondadas para um número inteiro de meses como, por exemplo, '1.5 years' se torna '1 year 6 mons'. As partes fracionárias de semanas e dias são calculadas como um número inteiro de dias e microssegundos, considerando 30 dias por mês e 24 horas por dia como, por exemplo, '1.75 months' se torna 1 mon 22 days 12:00:00. Apenas os segundos serão mostrados como frações na saída.

A Tabela 8.17 mostra alguns exemplos de entradas válidas para interval.

Tabela 8.17. Entrada de intervalo

ExemploDescrição
1-2formato padrão SQL: 1 ano 2 meses
3 4:05:06formato padrão SQL: 3 dias 4 horas 5 minutos 6 segundos
1 year 2 months 3 dias 4 hours 5 minutes 6 segundosformato tradicional do Postgres: 1 ano 2 meses 3 dias 4 horas 5 minutos 6 segundos
P1Y2M3DT4H5M6Sformato com designadores ISO 8601: mesmo significado acima
P0001-02-03T04:05:06formato alternativo ISO 8601: mesmo significado acima

Exemplo:

SELECT '1-2' ::interval,
       '3 4:05:06' ::interval,
       '1 year 2 months 3 days 4 hours 5 minutes 6 seconds'::interval;

   interval    |    interval     |           interval
---------------+-----------------+-------------------------------
 1 year 2 mons | 3 days 04:05:06 | 1 year 2 mons 3 days 04:05:06
(1 linha)

8.5.5. Saída de intervalo #

Conforme mencionado anteriormente, o PostgreSQL armazena os valores do tipo de dados interval como meses, dias e microssegundos. Para a saída, o campo de meses é convertido em anos e meses dividindo por 12. O campo de dias é mostrado tal como está. O campo de microssegundos é convertido em horas, minutos, segundos e frações de segundo. Portanto, meses, minutos e segundos nunca serão mostrados excedendo os limites 0–11, 0–59 e 0–59, respectivamente, mas os campos mostrados com anos, dias e horas podem ser muito grandes. (As funções justify_days e justify_hours podem ser usadas se for desejado transpor valores grandes de dias ou horas para o campo imediatamente superior.)

O formato de saída do tipo de dados interval pode ser definido como sendo um destes quatro estilos: sql_standard, postgres, postgres_verbose, ou iso_8601, usando o comando SET intervalstyle. O padrão é o formato postgres. A Tabela 8.18 mostra exemplos de cada um destes quatro estilos de saída.

O estilo sql_standard produz uma saída em conformidade com a especificação do padrão SQL para literais de intervalo, se o valor do intervalo estiver de acordo com as restrições do padrão (somente ano e mês, ou somente hora do dia, sem mistura de componentes positivos e negativos). Caso contrário, a saída se parece com um literal de ano-mês padrão seguido por um literal de dia-hora, com sinais explícitos adicionados para desambiguar intervalos com sinais mistos.

A saída do estilo postgres corresponde à saída do PostgreSQL nas versões anteriores a 8.4 quando o parâmetro DateStyle estava definido como ISO.

A saída do estilo postgres_verbose corresponde à saída do PostgreSQL nas versões anteriores a 8.4 quando o parâmetro DateStyle estava definido como não-ISO.

A saída do estilo iso_8601 corresponde ao formato com designadores descrito na seção 4.4.3.2 do padrão ISO 8601.

Tabela 8.18. Exemplos de estilo de saída de intervalo

Especificação do estiloIntervalo ano e mêsIntervalo hora do diaIntervalo misto
sql_standard1-23 4:05:06-1-2 +3 -4:05:06
postgres1 year 2 mons3 days 04:05:06-1 year -2 mons +3 days -04:05:06
postgres_verbose@ 1 year 2 mons@ 3 days 4 hours 5 mins 6 secs@ 1 year 2 mons -3 days 4 hours 5 mins 6 secs ago
iso_8601P1Y2MP3DT4H5M6SP-1Y-2M3D​T-4H-5M-6S



[43] zona horária: Os fusos horários estão centrados nos meridianos das longitudes múltiplas de 15°; as zonas horárias seguem os fusos horários de forma aproximada. Os fusos horários são definidos geograficamente, enquanto que as zonas horárias são definidas politicamente. Wikipédia - Fuso horário (N. T.)

[44] Formatos de data e hora: Este documento define um perfil da ISO 8601, o Padrão Internacional para a representação de datas e horas. A ISO 8601 descreve um grande número de formatos de data/hora. Para reduzir a margem de erro e a complexidade do software, é útil restringir os formatos aceitos a um pequeno número. Este perfil define alguns formatos de data/hora, provavelmente satisfazendo a maioria dos requisitos. W3C Date and Time Formats (N. T.)

[45] As regras para zona horária e horário de verão são controladas por governos individualmente. Elas às vezes são alterados com pouca antecedência, e suas histórias e futuros planejados são frequentemente registrados apenas de forma intermitente. Aqui está um resumo das tentativas de organizar e registrar dados relevantes nessa área. IANA - Sources for time zone and daylight saving time data (N. T.)

[46] O comando do Linux timedatectl list-timezones lista todas as zonas horárias disponíveis, uma por linha. Os valores dessa lista podem ser usados para definir a zona horária do sistema usando set-timezone. (N. T.)