Pular para o conteúdo
LeedyBox
Apoiar

Timestamps Unix explicados

Um timestamp Unix é um único número que representa um momento no tempo. É fácil de armazenar e comparar, mas unidades, fusos horários e formatos de texto causam muitos erros de conversão.

O que é o tempo Unix

O tempo Unix (também chamado de epoch time ou tempo POSIX) conta os segundos desde 1970-01-01 00:00:00 UTC, a época Unix (Unix epoch). 0 é a própria época, 1700000000 é 2023-11-14 22:13:20 UTC, e valores negativos são momentos anteriores a 1970: -1 é 1969-12-31 23:59:59 UTC.

O número não contém fuso horário: ele descreve o mesmo momento em qualquer lugar, o que o torna prático para armazenar, ordenar e comparar eventos.

O tempo Unix ignora os segundos bissextos: todo dia tem exatamente 86.400 segundos. Quando um segundo bissexto é acrescentado ao UTC, os sistemas repetem um segundo ou o distribuem por um período mais longo ("smearing"), então uma diferença que abrange um segundo bissexto é um segundo menor do que o tempo que de fato transcorreu.

Segundos, milissegundos, microssegundos ou nanossegundos?

Muitos sistemas contam em unidades menores, e o número não diz qual é a unidade. O mesmo momento pode aparecer como quatro números muito diferentes:

Unidade 2023-11-14 22:13:20 UTC Dígitos (2001–2286) Comum em
Segundos 1700000000 10 date +%s, muitas APIs, claims exp de JWT
Milissegundos 1700000000000 13 Date.now() no JavaScript, System.currentTimeMillis() no Java
Microssegundos 1700000000000000 16 Alguns bancos de dados e sistemas de log
Nanossegundos 1700000000000000000 19 UnixNano() no Go, time.time_ns() no Python

Contar os dígitos é a verificação mais rápida para datas atuais. O conversor do LeedyBox usa a mesma ideia: valores até 1011 são lidos como segundos, até 1014 como milissegundos, até 1017 como microssegundos, e valores maiores como nanossegundos. Essa regra prática falha para datas muito distantes de hoje, então confira a unidade quando um resultado parecer estranho.

A precisão também importa. Os números do JavaScript representam inteiros com exatidão apenas até 253 (cerca de 9 × 1015), então um valor em nanossegundos como 1700000000123456789 perde os últimos dígitos quando é lido como um número comum. Mantenha esses valores como strings ou use BigInt; o conversor faz isso internamente. Para ler o claim exp de um token, decodifique-o com a ferramenta Base64 / URL / JWT.

Fusos horários e horário de verão

Para mostrar um timestamp como data e hora, você precisa de um fuso horário. O UTC é a referência; o horário local aplica um deslocamento, como +09:00 em Seul ou −05:00 em Nova York no inverno.

Prefira nomes de fuso horário IANA, como Asia/Seoul ou America/New_York, a deslocamentos fixos e abreviações: um nome carrega o histórico do fuso e suas regras de horário de verão, enquanto uma abreviação como CST representa vários fusos. As regras vêm do banco de dados de fusos horários, que muda várias vezes por ano, e navegadores, sistemas operacionais e linguagens trazem as próprias cópias dele, então os resultados para datas passadas ou futuras podem variar.

O horário de verão cria dois casos complicados quando você converte um horário local em timestamp:

  • Lacuna: quando os relógios são adiantados, alguns horários locais não existem. Em America/New_York, 2026-03-08 02:30 é pulado porque os relógios saltam de 02:00 para 03:00.
  • Sobreposição: quando os relógios são atrasados, alguns horários locais acontecem duas vezes. 2026-11-01 01:30 ocorre uma vez em EDT (UTC−04:00) e de novo uma hora depois em EST (UTC−05:00).

As bibliotecas resolvem esses casos de formas diferentes. O conversor do LeedyBox usa o horário válido seguinte em uma lacuna (03:30, neste exemplo) e a primeira ocorrência em uma sobreposição, e explica isso em uma nota. Tarefas agendadas enfrentam o mesmo problema; veja Como ler expressões cron.

ISO 8601, RFC 3339 e datas HTTP

Quando um momento precisa ser legível por pessoas, escreva-o em ISO 8601 ou no seu perfil mais rígido para a internet, o RFC 3339:

2023-11-14T22:13:20Z
2023-11-15T07:13:20+09:00
2023-11-14T22:13:20.500Z

Z significa UTC. Com Z ou um deslocamento, a string não é ambígua. Uma string sem nenhum dos dois, como 2023-11-14T22:13:20, é um horário local em um fuso desconhecido, e os parsers divergem sobre como interpretá-la.

Cabeçalhos HTTP como Last-Modified e Expires usam um formato mais antigo, derivado do formato de data do e-mail (RFC 2822, hoje RFC 5322), escrito em GMT: Tue, 14 Nov 2023 22:13:20 GMT.

O problema do ano 2038

Muitos sistemas mais antigos armazenam o tempo Unix em um inteiro de 32 bits com sinal. Seu maior valor, 2147483647, corresponde a 2038-01-19 03:14:07 UTC. Um segundo depois, o contador estoura para -2147483648, que é lido como 1901-12-13 20:45:52 UTC. Os sistemas operacionais e as linguagens atuais usam, em sua maioria, valores de tempo de 64 bits, que cobrem centenas de bilhões de anos, mas campos de 32 bits ainda aparecem em dispositivos embarcados, formatos de arquivo, colunas de bancos de dados e protocolos de rede. Se o seu código ou os seus dados armazenam segundos em 32 bits, planeje a mudança com antecedência e teste desde já datas posteriores a 2038.

Timestamps em código e bancos de dados

O JavaScript trabalha em milissegundos:

Math.floor(Date.now() / 1000);                  // tempo Unix atual em segundos
new Date(1700000000 * 1000).toISOString();      // "2023-11-14T22:13:20.000Z"
Date.parse("2026-10-03T09:00:00+09:00") / 1000; // 1790985600

O time.time() do Python retorna segundos como float. Passe tz=timezone.utc; caso contrário, fromtimestamp() retorna o horário local do computador sem fuso horário:

import time
from datetime import datetime, timezone

int(time.time())                                     # segundos
datetime.fromtimestamp(1700000000, tz=timezone.utc)  # 2023-11-14 22:13:20+00:00
datetime.fromisoformat("2026-10-03T09:00:00+09:00").timestamp()  # 1790985600.0

Em SQL, as funções variam conforme o banco de dados:

-- PostgreSQL
SELECT extract(epoch FROM now());   -- segundos, com fração
SELECT to_timestamp(1700000000);    -- timestamp with time zone
-- MySQL
SELECT UNIX_TIMESTAMP();
SELECT FROM_UNIXTIME(1700000000);   -- no fuso horário da sessão

Para o armazenamento, alguns hábitos evitam a maioria dos problemas:

  • Armazene em UTC os momentos que já aconteceram, seja em uma coluna de timestamp com fuso horário, seja como um inteiro de 64 bits cuja unidade faça parte do nome da coluna, como created_at_ms.
  • Armazene eventos locais futuros, como uma reunião às 09:00 em Seul, como data e hora locais mais o nome do fuso IANA, e calcule o timestamp quando necessário, para que uma mudança posterior nas regras não altere o horário da reunião.
  • Não misture unidades em uma mesma coluna; uma unidade errada faz o valor errar por um fator de 1.000 ou mais.

Perguntas frequentes

Por que meu timestamp é convertido em uma data de 1970?

Provavelmente o valor foi lido na unidade errada: segundos lidos como milissegundos caem em janeiro de 1970, e milissegundos lidos como segundos caem dezenas de milhares de anos no futuro. Conte os dígitos ou escolha a unidade no conversor.

Um timestamp Unix depende do meu fuso horário?

Não. Ele conta os segundos a partir de um momento fixo em UTC. Só a data e a hora exibidas para ele dependem do fuso horário.

O tempo Unix consegue representar um segundo bissexto?

Não. O tempo Unix trata todo dia como tendo 86.400 segundos, então um horário UTC como 23:59:60 não tem um timestamp próprio.