Há uma resposta longa e bastante elucidativa sobre as diferenças entre
TIMESTAMP WITH TIME ZONE
-vs-TIMESTAMP WITHOUT TIME ZONE
disponível no post SO Ignorando completamente os fusos horários em Rails e PostgreSQL .
O que eu gostaria de saber é: Existem casos de uso válidos para realmente usar TIMESTAMP WITHOUT TIME ZONE
ou deve ser considerado um antipadrão?
Isso é afirmado em muitos lugares, mas acho que vale a pena mencionar sempre quando comparamos
timestamp with time zone
com ostimestamp without time zone
tipos: otimestamp WITH time zone
não armazena as informações de fuso horário junto com o timestamp . O que ele faz é armazenar todos os dados no fuso horário UTC, conforme indicado nos documentos :É considerado válido para alguns usar
timestamp WITHOUT time zone
em situações em que (1) tudo está no mesmo fuso horário ou (2) a camada de aplicação trata o fuso horário e apenas armazena tudo em um determinado fuso horário (geralmente UTC). Mas também é considerado um anti-padrão, simples porque a solução correta para (1) é configurar o fuso horário para o fuso horário determinado para o sistema e (2) já está resolvido, pois o PostgreSQL já armazena tudo no mesmo fuso horário (UTC).Agora, com esses dois para baixo, eu posso vir com apenas um bom motivo para usar
timestamp WITHOUT time zone
. É quando você deseja armazenar eventos no futuro e que algum tipo de alerta deve ser acionado quando chegarmos a esse momento. Isso poderia ser bomtimestamp WITH time zone
se, e somente se, as regras definidas pelas leis da região sobre fuso horário nunca mudassem. A regra mais comum que muda é sobre a adoção ou não do horário de verão (DST).Por exemplo, imagine que você está, digamos,
2013-06-15
(ainda não em horário de verão) agendar algum evento para acontecer2013-01-15 10:00
(que já estaria em horário de verão), e em2013-06-15
sua região foi designado para adotar o horário de verão; mas, algum tempo depois disso, o governo mudou a regra e diz que sua região não vai mais usar o horário de verão, e de repente seu horário agendado passa a ser2013-01-15 11:00
(ao invés de10:00
), isso se você usartimestamp WITH time zone
, e mantenha suas configurações de TZ atualizadas. Claro que você também pode notar que é possível tratar tais casos também com fuso horário, se você acompanhar as mudanças de regras nas regiões/fusos horários de seu interesse e atualizar os registros afetados.Vale ressaltar que algumas regiões costumam mudar essas regras (como no Brasil, alguns estados - não todo o país - mudam frequentemente), mas na maioria dos casos isso muda muito antes, então seus usuários seriam afetados apenas por eventos agendados muito longe a hora atual.
Com tudo isso dito, só tenho mais uma sugestão. Se você tiver usuários, logs ou qualquer coisa em fusos horários diferentes, armazene o fuso horário de onde eles estão vindo e escolha e use
timestamp with time zone
. Dessa forma, você pode (1) cruzar eventos que acontecem mais próximos uns dos outros para diferentes fontes (independentemente de seus fusos horários) e (2) mostrar a hora original (a hora do relógio) em que o evento aconteceu.Sim. Existem casos de uso para
TIMESTAMP WITHOUT TIME ZONE
.TIMESTAMP WITH TIME ZONE
, nãoWITHOUT
.TIMESTAMP WITHOUT TIME ZONE
os valores não são um ponto na linha do tempo, nem momentos reais. Eles representam uma ideia aproximada sobre momentos potenciais , possíveis pontos na linha do tempo ao longo de um intervalo de cerca de 26 a 27 horas (o intervalo de fusos horários ao redor do globo). Eles não têm significado real até que você aplique um fuso horário ou offset-from-UTC .Ex: Natal
Por exemplo, digamos que você precise registrar o início dos feriados/dias santos.
Para registrar o fato de que o Natal começa depois da meia-noite de 25 de dezembro deste ano, precisamos dizer
2016-12-25 00:00:00
sem fuso horário. No início do dia do Papai Noel, ele visita Auckland NZ logo após a meia-noite, pois essa é uma das primeiras meia-noite do mundo. Então ele segue seu caminho para o oeste, quando a meia-noite seguinte acontece, logo chegando às Filipinas. Em seguida, as renas se movem em direção oeste, atingindo a Índia à meia-noite, o que ocorre várias horas após a meia-noite de Auckland. Muito mais tarde ainda é meia-noite em Paris FR, e ainda mais tarde é meia-noite em Montreal CA. Todas essas visitas do Papai Noel acontecem em diferentes momentos do tempo , mas todas aconteceram logo após a meia-noite, conforme a meia-noite de cada localidade.Portanto, gravar
2016-12-25 00:00:00
sem fuso horário como o início do Natal é informativo e legítimo, mas apenas vagamente. Até que você diga “Natal em Auckland” ou “Natal em Montreal”, não temos um momento específico no tempo. Se você estiver gravando o momento real cada vez que o trenó pousar, você usariaTIMESTAMP WITH TIME ZONE
em vez doWITHOUT
tipo.Semelhante ao Natal é a véspera de Ano Novo. Quando o baile da Times Square cai em Nova York , as pessoas em Seattle ainda estão bebendo champanhe e preparando suas buzinas de festa . No entanto, registraríamos a ideia do momento do Ano Novo como
2017-01-01 00:00:00
em um arquivoTIMESTAMP WITHOUT TIME ZONE
. Por outro lado, se quisermos registrar quando a bola caiu em Nova York, ou quando as pessoas em Seattle tocaram suas buzinas, usaríamosTIMESTAMP WITH TIME ZONE
(nãoWITHOUT
) para registrar esses momentos reais, cada um com três horas de intervalo.Ex: Turnos de Fábrica
Outro exemplo pode ser a gravação de uma política que envolve o tempo de relógio de parede em vários locais. Digamos que temos fábricas em Detroit, Düsseldorf e Delhi. Se dissermos que em todas as três fábricas o primeiro turno começa às 6h com intervalo para o almoço às 11h30, isso pode ser registrado como um
TIMESTAMP WITHOUT TIME ZONE
. Novamente, esta informação é útil de forma vaga, mas não indica um momento específico até que apliquemos um fuso horário. Um novo dia amanhece mais cedo no leste. Assim, a fábrica de Delhi será a primeira a abrir às 6h. Horas depois, a fábrica de Düsseldorf começa a trabalhar às 6h. Mas a fábrica de Detroit não abrirá até seis horas depois, quando as 6 da manhã acontecerem.Compare essa ideia (de quando o turno da fábrica geralmente começa) com o fato histórico de quando cada operário da fábrica marcou o ponto para começar seu turno em um determinado dia. O clock-in é um momento real, um ponto real na linha do tempo. Portanto, registraríamos isso em uma coluna de tipo
TIMESTAMP WITH TIME ZONE
em vez doWITHOUT
tipo.Então, sim, existem casos de uso legítimos para
TIMESTAMP WITHOUT TIME ZONE
. Mas na minha experiência com aplicativos de negócios, eles são relativamente raros. Nos negócios, tendemos a nos preocupar com os momentos reais: quando a fatura realmente chegou, quando exatamente esse contrato entra em vigor, em que momento essa transação bancária foi executada. Então, em situações tão comuns, queremos oTIMESTAMP WITH TIME ZONE
tipo.Para mais discussão, consulte minha resposta à pergunta semelhante, devo armazenar carimbos de data/hora UTC ou hora local para turnos
Postgres
Observe que o Postgres especificamente nunca salva as informações de fuso horário especificadas ao inserir um carimbo de data/hora.
TIMESTAMP WITH TIME ZONE
TIMESTAMP WITH TIME ZONE
comoTIMESTAMP WITH RESPECT FOR TIME ZONE
.TIMESTAMP WITHOUT TIME ZONE
O padrão SQL mal toca em questões de tipos de dados de data e hora e comportamento. Assim, o banco de dados varia muito no tratamento de data e hora.
Eu gostaria de adicionar outra visão a isso, que vai contra muito do que foi escrito nas outras respostas. Na minha opinião
timestamp with time zone
, tem muito poucos casos de uso válidos etimestamp without time zone
, em geral, deve ser o preferido.Primeiro, você deve entender o padrão "UTC em todos os lugares", que geralmente é recomendado para todos os aplicativos que não possuem requisitos muito especiais. Significa simplesmente que seu aplicativo deve representar todos os seus carimbos de data/hora em UTC, em todos os lugares, o tempo todo. Claro, você estará mostrando a data/hora local para os usuários, mas a ideia é convertê-los na borda do seu programa, ao renderizar a visualização. Este é o lugar certo para combinar o timestamp UTC (que você pode ter carregado de um banco de dados) e o fuso horário do usuário (que pode ter vindo do navegador) em um timestamp local.
Se você está seguindo esse padrão, então
timestamp with time zone
é um antipadrão. Tudo o que esse tipo faz é fazer com que o PostgreSQL realize conversões de fuso horário ao ler e gravar registros de data e hora, com base naTimeZone
variável de sessão do PostgreSQL. Em vez de lidar com fusos horários nas bordas de seu aplicativo, você os introduziu em seu coração, na própria comunicação com seu banco de dados. Você deve ter o cuidado de sempre ter o PostgreSQLTimeZone
configurado corretamente em todos os momentos, adicionando outro ponto desnecessário de falha e confusão.E para quê? Se você estiver seguindo o padrão UTC em todos os lugares, seu aplicativo terá apenas timestamps UTC de qualquer maneira; então por que pedir ao seu banco de dados para fazer conversões de fuso horário neles? Você pode simplesmente armazená-los em uma
timestamp without time zone
coluna e tratá-los como se fosse sempre UTC. Sem conversões, sem fusos horários, sem complicações.EDIT 2021-10-01 : Depois de muito tempo, gostaria de matizar o acima ... É verdade que a representação de texto
timestamp with time zone
é um fuso horário local e isso introduz uma conversão que geralmente não é desejada. No entanto, muitos drivers PostgreSQL lêem e escrevemtimestamptz
como um timestamp UTC puro (em qualquer representação apropriada na linguagem); quando for esse o caso,timestamptz
definitivamente deve ser preferido para manter os carimbos de data e hora UTC.Como mantenedor do driver .NET PostgreSQL (Npgsql), estamos fazendo esta alteração exata na próxima versão 6.0: Npgsql simplesmente retornará um timestamp UTC contendo o valor exato como está no banco de dados, sem nenhuma conversão ( veja o notas de lançamento ).
Pode parecer tentador armazenar e processar datas/horas na hora local se seu aplicativo estiver limitado a um único fuso horário, mas acredito que isso seja um erro.
Ao voltar do horário de verão para o horário padrão, uma hora no horário local é repetida (assumindo que a diferença é de uma hora). Onde eu moro, isso geralmente acontece por volta das 2h da manhã, então o horário local é 01:58, 01:59, 01:00 e só avança para 02:00 no final da hora repetida.
Se você tentar ordenar eventos por hora usando a hora local, isso significa que eventos de duas horas separadas são misturados e não aparecem na ordem em que realmente aconteceram.
Em comparação, o UTC não tem esse problema e ordena de forma limpa. Portanto, mesmo ao trabalhar com apenas um fuso horário, você deseja que o banco de dados armazene e processe horários em UTC e converta de/para hora local para entrada/exibição. Este é o comportamento de TIMESTAMP WITH TIME ZONE.
O
date
carimbo de data/hora também não inclui informações de fuso horário, mas muitas pessoas o usam.Claro, isso por si só não é uma resposta.
É válido usar
timestamp
edate
para quaisquer carimbos de data e hora e datas que estejam sempre no mesmo fuso horário ou que estejam sendo armazenados em relação a algum fuso horário conhecido.Se o fuso horário for sempre o mesmo ou implícito, é mais antipadrão armazená-lo do que não armazená-lo (informações redundantes).
Os carimbos de data/hora também podem ser usados para armazenar informações técnicas, como as usadas em logs de aplicativos ou para medições de desempenho. Nesse caso, o fuso horário também pode não ser importante.
Por outro lado, se você estiver projetando ou trabalhando em um sistema distribuído ou em qualquer sistema em que partes do sistema serão distribuídas em diferentes fusos horários, pode ser considerado um antipadrão não usar
timestamp with timezone
, embora alguns sistemas possam ser projetados para executar em um fuso horário, por exemplo, UTC. Nesse caso, a lógica do fuso horário pode estar sendo empurrada para a camada do aplicativo - mas eu consideraria isso um antipadrão, sim.2 exemplos de casos de uso:
Programando desde os anos 90... Acho que nunca tive um caso de uso que
WITHOUT
fosse preferível aTIMESTAMPTZ
, supondo que eu pudesse escolher entre ambos.Reservas Futuras ,
Você quer permitir que as pessoas reservem uma hora e data no futuro e não ter reservas saltando quando os políticos de repente decidem mudar para as regras de horário de verão ou fuso horário em você.
Se a reserva estiver perto o suficiente para mostrar que você pode confiar em políticos para não destruir seus dados, isso pode não ser um problema.
Todo o resto é provavelmente melhor representado em timestamptz
Felizmente, eles nunca fazem alterações retroativas no horário de verão, portanto, usar timestamtz para registrar dados históricos funciona bem (especialmente para eventos na hora dobrada)