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.