Unix Timestamp vs string datetime em APIs — qual deve usar?

Toda API que lida com tempo tem de fazer uma escolha: representar datas e horas como Unix timestamps (inteiros) ou como strings datetime formatadas (como ISO 8601). Ambas funcionam. Ambas são amplamente usadas. Mas comportam-se de forma diferente, e essa escolha tem consequências posteriores para cada cliente que consome a sua API.

Este artigo percorre os trade-offs para que possa tomar uma decisão informada ou entender com o que está a trabalhar ao consumir uma API existente.

Para consultas rápidas e conversões de timestamp, o Conversor de Unix Timestamp lida com ambos os formatos.

Como cada formato se apresenta

Unix timestamp (inteiro, segundos): `txt 1712505600 `

Unix timestamp (inteiro, milissegundos): `txt 1712505600000 `

String datetime ISO 8601 (UTC): `txt 2024-04-07T16:00:00Z `

String datetime ISO 8601 (com offset de fuso horário): `txt 2024-04-07T12:00:00-04:00 `

RFC 2822 (comum em cabeçalhos de email e APIs mais antigas): `txt Sun, 07 Apr 2024 16:00:00 +0000 `

O argumento a favor de Unix timestamps

Sem ambiguidade de fuso horário

Um Unix timestamp está sempre em UTC. Não há componente de fuso horário para interpretar, nenhum offset para analisar e nenhum risco de ler mal a abreviatura do fuso horário. 1712505600 significa exatamente um momento no tempo, independentemente de onde o servidor ou o cliente está a correr.

Este é o argumento mais forte a favor de timestamps na comunicação backend-para-backend. O tratamento de fusos horários é uma das fontes mais comuns de bugs relacionados com datas. Timestamps evitam esse problema por completo.

Aritmética simples

Comparar duas timestamps, calcular a diferença entre elas, verificar se uma expiração já passou, adicionar 24 horas: tudo isso são operações triviais com inteiros.

// O token expirou?
const isExpired = Date.now() / 1000 > tokenExp;

// Adicionar 24 horas a uma timestamp
const tomorrow = now + 86400;

Com strings datetime, as mesmas operações exigem parsing, normalização de fuso horário e chamadas a bibliotecas de datas.

Compactos e ordenáveis

Timestamps são compactos: 10 dígitos para segundos, 13 para milissegundos, e ordenam corretamente como inteiros. Strings datetime só ordenam corretamente como strings no formato ISO 8601 (YYYY-MM-DD...). Outros formatos, como "April 7, 2024" ou "07/04/2024", não ordenam corretamente como strings sem parsing.

Armazenamento eficiente

Um inteiro ocupa 4 ou 8 bytes numa coluna de base de dados. Uma string datetime numa coluna VARCHAR ocupa 20 a 30 bytes. Em tabelas grandes com milhões de linhas, essa diferença importa.

O argumento a favor de strings datetime

Legíveis por humanos sem conversão

Quando inspeciona uma resposta de API num browser, ficheiro de log ou ferramenta de debugging, 2024-04-07T16:00:00Z diz-lhe imediatamente o que está a ver. 1712505600 não lhe diz nada sem conversão.

Esta é uma diferença real de qualidade de vida durante desenvolvimento e debugging. Se um campo created_at mostrar 1712505600, tem de o colar num conversor para verificar se está correto. Se mostrar 2024-04-07T16:00:00Z, percebe imediatamente.

Representação de hora local

Uma string datetime pode incluir um offset de fuso horário: 2024-04-07T12:00:00-04:00. Isto é útil para eventos intrinsecamente ligados a uma hora local: uma reunião marcada para as 9:00 em Nova Iorque, um horário de abertura de negócio, uma partida de voo.

Um Unix timestamp pode armazenar essa informação, mas a hora local tem de ser reconstruída no momento da apresentação usando metadados de fuso horário armazenados. Strings datetime podem transportar o offset diretamente.

Melhor interoperabilidade com bibliotecas de datas

Muitos frameworks frontend e bibliotecas de datas analisam strings ISO 8601 nativamente. O new Date("2024-04-07T16:00:00Z") do JavaScript funciona diretamente. O datetime.fromisoformat() do Python funciona diretamente. A experiência de desenvolvimento é mais suave.

Mais fáceis de validar

Uma string datetime tem uma estrutura visível. Se estiver mal formada, isso costuma ser óbvio. 2024-13-07T16:00:00Z tem um mês inválido; consegue ver isso sem a passar por um conversor. Um Unix timestamp como 17125056000 (com um zero extra) é mais difícil de detetar como incorreto sem conhecer o intervalo esperado.

Armadilhas comuns

Confusão entre segundos e milissegundos

Unix timestamps podem estar em segundos ou milissegundos, e nem todos os sistemas concordam sobre qual usar. JavaScript usa milissegundos (Date.now() devolve um número de 13 dígitos). A maioria das linguagens server-side e bases de dados usa segundos (10 dígitos). Se um frontend em JavaScript enviar uma timestamp para um backend que espera segundos, o valor será 1.000 vezes maior do que o esperado, resultando em datas no ano 55.000.

A solução: seja explícito na documentação da sua API sobre qual unidade é usada. O Conversor de Unix Timestamp deteta em que formato um valor está com base na contagem de dígitos, o que é útil para debugging rápido.

Strings datetime ingênuas (sem fuso horário)

Uma string datetime sem indicador de fuso horário, como 2024-04-07 16:00:00, é ambígua. Isso é UTC? Hora local do servidor? Hora local do utilizador? Bibliotecas diferentes tratam isto de forma diferente, e o comportamento costuma surpreender.

Use sempre strings datetime com informação de fuso horário em respostas de API. 2024-04-07T16:00:00Z (UTC) ou 2024-04-07T12:00:00-04:00 (offset explícito), nunca hora local simples sem qualificador.

Inconsistências de parsing entre linguagens

ISO 8601 é um padrão, mas nem todas as implementações analisam corretamente todas as variantes válidas de ISO 8601. A variante com microssegundos (2024-04-07T16:00:00.123456Z) é válida em ISO 8601, mas não é suportada por todos os parsers. O separador T por vezes pode ser substituído por um espaço (2024-04-07 16:00:00Z) válido em SQL, mas não em parsers estritos de ISO 8601.

Se usar strings datetime, teste se o seu formato é corretamente analisado em todas as linguagens e bibliotecas usadas pelos seus clientes.

O que a maioria das APIs de produção realmente faz

A convenção dominante em APIs REST modernas é strings datetime ISO 8601 em UTC para campos voltados para humanos (created_at, updated_at, published_at) e Unix timestamps em segundos para campos de autenticação e segurança (exp, iat, nbf em JWTs, expiração de token).

Esta combinação faz sentido: timestamps voltadas para humanos beneficiam da legibilidade; timestamps de segurança beneficiam da aritmética compacta com inteiros e da ausência de overhead de parsing.

A API do GitHub usa strings ISO 8601. A Stripe usa Unix timestamps. A Twilio usa ISO 8601. O Twitter/X usa Unix timestamps em milissegundos. Não existe um padrão universal na indústria; vai encontrar ambos.

Um framework simples de decisão

Use Unix timestamps quando:

  • Está a armazenar ou transmitir timestamps principalmente para computação (ordenação, aritmética, verificações de expiração)
  • Está a trabalhar num contexto backend-para-backend em que a legibilidade humana é menos importante
  • Precisa de armazenamento compacto e comparação simples
  • Quer evitar por completo o tratamento de fusos horários

Use strings datetime ISO 8601 quando:

  • A timestamp será lida por developers ao depurar respostas de API
  • A hora está ligada a um fuso horário específico ou contexto local
  • Está a construir uma API pública onde a experiência de desenvolvimento importa
  • Precisa de representar horas com precisão de subsegundos de forma fiável

Seja qual for a sua escolha, documente-a claramente: a unidade (segundos ou milissegundos para timestamps), o fuso horário (sempre UTC para timestamps; inclua offset para strings) e o formato (variante ISO 8601 para strings). Ambiguidade na representação do tempo é uma fonte fiável de bugs difíceis de diagnosticar.