Milissegundos vs segundos: a confusão de unidades que quebra cada app

O bug de timestamp mais comum é passar milissegundos onde se esperam segundos, ou o contrário. Aprenda a regra de 10 vs 13 dígitos, os padrões de cada linguagem, as implicações em bancos e os padrões de conversão seguros.

Por que existem dois padrões

O tempo Unix foi originalmente definido em segundos — um inteiro parecia natural para um sistema que incrementava a cada tique do relógio. O objeto Date do JavaScript surgiu em 1995 e escolheu milissegundos para suportar a temporização de eventos abaixo de um segundo no navegador. Muitos bancos e linguagens de backend mantiveram os segundos Unix como padrão. Hoje, ambos os padrões coexistem em todo código que cruza a fronteira JavaScript-servidor, e por isso um valor pode parecer válido e ainda representar uma data a dezenas de milhares de anos.

Qual unidade cada linguagem usa

A forma mais segura de lembrar a divisão: as APIs Date do navegador geralmente querem milissegundos, as APIs de servidor no estilo Unix geralmente expõem segundos, e as bibliotecas de tempo mais novas costumam oferecer ambos. Não deduza a unidade só pela linguagem ao ler a documentação de uma API de terceiros; verifique a descrição do campo e os exemplos.

  • Milliseconds: JavaScript Date.now(), Java System.currentTimeMillis(), Java Instant.toEpochMilli(), .NET ToUnixTimeMilliseconds()
  • Seconds: Python time.time() (float), PHP time(), Go time.Now().Unix(), Ruby Time.now.to_i, C time(NULL), PostgreSQL EXTRACT(EPOCH)
  • Both: Rust — duration.as_secs() for seconds, duration.as_millis() for milliseconds
  • Python note: time.time() returns a float, so milliseconds are available as int(time.time() * 1000)

Detectar a unidade pelo valor

Uma heurística confiável para datas modernas: um número de 10 dígitos são segundos; um de 13 dígitos são milissegundos. Os segundos Unix atuais estão em torno de 1,7–2,1 bilhões (10 dígitos) e só chegarão a 13 dígitos no ano 33658. Os milissegundos Unix atuais já têm 13 dígitos. A heurística é mais forte de 2000 até alguns milhares de anos à frente; para datas históricas, negativas ou fixtures de teste compactas, use unidades explícitas em vez de adivinhar.

  • valor de 10 dígitos → segundos (ex.: 1700000000 = 2023-11-14 UTC)
  • valor de 13 dígitos → milissegundos (ex.: 1700000000000 = 2023-11-14 UTC)
  • valor de 16 dígitos → microssegundos (divida por 1,000,000 para segundos)
  • valor negativo → data anterior a 1 de janeiro de 1970 (segundos ou milissegundos)

Padrões de conversão seguros

A conversão em si é aritmética simples; o difícil é escolher onde ela deve acontecer. Converta no limite do sistema, nomeie o valor convertido e evite passar números brutos ambíguos por várias camadas.

  • Seconds to milliseconds: seconds * 1000
  • Milliseconds to whole seconds — JavaScript: Math.floor(ms / 1000)
  • Milliseconds to whole seconds — Python: ms // 1000
  • Milliseconds to whole seconds — Go: ms / 1000 (integer division)
  • Universal guard in JavaScript: const toMs = ts => ts < 1e11 ? ts * 1000 : ts

Como os bugs de unidade aparecem em produção

Um bug de segundos-vs-milissegundos costuma sobreviver à validação porque ambos os valores são apenas números. Costuma aparecer depois como uma data impossível: janeiro de 1970 no JavaScript quando segundos foram tratados como milissegundos, ou um ano muito distante quando um backend tratou milissegundos como segundos.

  • Data de 1970 na UI do JavaScript → segundos foram passados a new Date() sem multiplicar por 1000
  • Ano 50000+ em Python, Go ou PHP → milissegundos foram passados a uma API que esperava segundos
  • Tokens expirados que nunca expiram → timestamp de expiração salvo na unidade errada
  • Entradas de cache que somem na hora → milissegundos divididos duas vezes ou segundos multiplicados duas vezes
  • Gráficos de analytics com intervalos vazios → os limites da consulta usam unidade diferente dos timestamps de eventos salvos

Convenções de nomenclatura em APIs e bancos

Uma pequena convenção de nomenclatura evita a maioria desses bugs. Nunca publique um campo de API chamado timestamp a menos que a documentação seja excepcionalmente clara. Prefira nomes de campo que incluam o significado e a unidade.

  • createdAtMs — Unix milliseconds, best for JavaScript clients
  • createdAtSeconds — Unix seconds, common for backend services
  • createdAtIso — ISO 8601 string, useful for human-readable API responses
  • expiresAtUnixSeconds — explicit enough for auth tokens and signed URLs
  • event_time TIMESTAMPTZ — native database time, with conversion handled by the database

FAQ milissegundos vs segundos

Um timestamp de 13 dígitos é sempre milissegundos?
Para timestamps Unix reais modernos, sim: 13 dígitos geralmente significam milissegundos. Timestamps em segundos muito distantes no futuro também podem chegar a 13 dígitos, então sistemas críticos devem carregar metadados de unidade explícitos.
Devo armazenar segundos ou milissegundos?
Armazene a unidade que seu sistema usa naturalmente, mas documente-a e mantenha consistente. Sistemas com muito JavaScript costumam usar milissegundos; backends no estilo Unix e muitos bancos costumam usar segundos ou colunas datetime nativas.
Por que usar Math.floor(ms / 1000) em vez de ms / 1000?
Os segundos Unix geralmente são segundos inteiros. Math.floor remove a parte fracionária para que APIs que esperam segundos inteiros não recebam um decimal.
Como converto milissegundos em segundos?
Divida por 1000 e descarte a fração: Math.floor(ms / 1000) no JavaScript, ms // 1000 no Python, ou ms / 1000 com divisão inteira no Go. Para o outro sentido, multiplique os segundos por 1000.