FNSP Web Page

Datas na base de dados: guarde sempre em UTC

É uma das decisões mais baratas de tomar no início e mais caras de corrigir depois: em que fuso horário é que as datas ficam guardadas.

A resposta é sempre UTC, e converte-se para o fuso de quem lê no último momento possível — na altura de mostrar.

1. Porque é que o fuso local não serve

  • O servidor muda de máquina e o fuso muda com ele. As datas antigas passam a mentir.

  • Há dias com 23 horas e dias com 25, por causa da mudança da hora. Em outubro, a hora entre as 01:00 e as 02:00 acontece duas vezes: uma data guardada nesse intervalo é ambígua e não há forma de a desfazer.

  • Duas pessoas em fusos diferentes ordenam a mesma lista de forma diferente.

2. Em Postgres: timestamptz, não timestamp

-- Guarda um instante. Converte para UTC ao escrever.
criado_em TIMESTAMPTZ NOT NULL DEFAULT NOW()

-- Guarda números num relógio, sem dizer de onde. Evitar.
criado_em TIMESTAMP NOT NULL

O nome engana: o timestamptz não guarda o fuso. Guarda um instante — normaliza para UTC ao escrever e converte para o fuso da sessão ao ler. É precisamente o que se quer.

3. Quando o que interessa é o dia

Nem tudo é um instante. Uma data de nascimento, ou o dia em que um artigo foi publicado, não têm hora nem fuso — se as guardar como instante, alguém do outro lado do Atlântico vê o dia anterior.

publicado_em DATE NOT NULL

4. A conversão é na fronteira

// Do lado do servidor: sempre o instante
const criadoEm = new Date(); // internamente é UTC

// À saída, para quem lê
new Intl.DateTimeFormat('pt-PT', {
  dateStyle: 'short',
  timeStyle: 'short',
  timeZone: 'Europe/Lisbon',
}).format(criadoEm);

A regra em três palavras: guardar em UTC, mostrar em local. E nunca, nunca guardar uma data já formatada como texto — é o erro que obriga a adivinhar mais tarde o que "03/04/2009" queria dizer.

Comentários

Ainda ninguém comentou este artigo.

Voltar ao blog

Gostávamos de saber quantas pessoas visitam o site, com o Google Analytics. Sem a sua autorização não corre nada. Política de Privacidade.