Como Converter Entre Formatos de Hora
Os formatos de tempo variam entre sistemas, APIs e países. Timestamps Unix em respostas de API, ISO 8601 em bases de dados, relógios de 12 horas nos EUA, relógios de 24 horas na Europa: converter entre eles é uma necessidade constante para programadores e para qualquer pessoa que trabalhe com dados internacionais. Compreender porque cada formato existe, onde brilha e onde morde transforma a conversão num reflexo rápido em vez de uma fonte recorrente de bugs subtis.
Uma breve história dos formatos de tempo
Padronizar o tempo é mais antigo que a internet. Em 1884 a Conferência Internacional do Meridiano estabeleceu a hora média de Greenwich e o meridiano de origem, o que deu ao mundo uma referência comum pela primeira vez. O relógio de 24 horas espalhou-se pela aviação e pelos militares pela mesma razão: elimina a ambiguidade AM/PM que transforma uma reserva de meia-noite num voo de meio-dia.
O tempo Unix chegou com o kernel Unix original em 1971, contando segundos desde 1 de janeiro de 1970 UTC (a "epoch"). A escolha foi pragmática: um inteiro de 32 bits cobria décadas, ordenar timestamps significava ordenar números, e calcular intervalos era uma subtração. O ISO 8601 chegou em 1988 para padronizar o lado legível: ano-mês-dia em ordem big-endian, T como separador data/hora, e Z para UTC. O RFC 3339 (2002) é um perfil mais restritivo do ISO 8601 desenhado para protocolos de internet. O RFC 2822 (2001) define o formato estilo e-mail com nomes de dia e offsets. Cada formato resolve um problema real; nenhum substitui os outros por completo.
Formatos de tempo comuns
Seis formatos cobrem quase tudo o que vai encontrar na prática. A primeira coluna é o nome que verá na documentação; a coluna de exemplo mostra como 14:30 de 7 de abril de 2024 UTC se parece.
| Formato | Exemplo | Usado por |
|---|---|---|
| Timestamp Unix (segundos) | 1712502600 | APIs, bases de dados, tokens JWT, linhas de log |
| Timestamp Unix (ms) | 1712502600000 | JavaScript, Java, Android |
| Timestamp Unix (microssegundos) | 1712502600000000 | Postgres, Kafka, OpenTelemetry |
| ISO 8601 / RFC 3339 | 2024-04-07T14:30:00Z | APIs JSON, bases de dados, logs |
| RFC 2822 | Sun, 07 Apr 2024 14:30:00 +0000 | Cabeçalhos de e-mail, cabeçalhos HTTP |
| 24 horas | 14:30 | Europa, militar, aviação |
| 12 horas | 2:30 PM | EUA, uso informal |
| Dia do ano (juliano) | 2024-098 | Aviónica, dados científicos |
| Data semana | 2024-W14-7 | Planeamento industrial, banca |
A maioria das equipas fica-se por milissegundos Unix para armazenamento e ISO 8601 para trânsito, com formatos de exibição escolhidos por locale. A escolha importa menos que a consistência: escolha um formato principal, documente-o, e converta nas bordas.
Referência rápida de conversão
12 horas para 24 horas
O relógio de 12 horas tem duas peculiaridades: 12 AM é meia-noite (o início do dia) e 12 PM é meio-dia. A tabela abaixo cobre os casos que apanham as pessoas.
| 12 horas | 24 horas |
|---|---|
| 12:00 AM (meia-noite) | 00:00 |
| 1:00 AM | 01:00 |
| 11:59 AM | 11:59 |
| 12:00 PM (meio-dia) | 12:00 |
| 12:01 PM | 12:01 |
| 1:00 PM | 13:00 |
| 6:00 PM | 18:00 |
| 11:59 PM | 23:59 |
Timestamps para datas
O conversor epoch traduz instantaneamente timestamps Unix para datas legíveis e vice-versa. O conversor deteta automaticamente os formatos de segundos (10 dígitos) e milissegundos (13 dígitos), por isso pode colar um valor de qualquer fonte sem se preocupar com a unidade.
Uma verificação de bom senso útil: divida por 86400 (segundos num dia) e some 1970 dias para localizar mentalmente qualquer timestamp. 1712502600 / 86400 ~ 19820 dias, cerca de 54 anos depois de 1970, o que o coloca em 2024. Não é preciso mas chega para apanhar erros de fator 1000 num relance.
Exemplos de conversão em código
A maioria dos programadores acaba por precisar de converter timestamps em código. As APIs principais são curtas:
- JavaScript,
new Date(1712502600 * 1000).toISOString()devolve2024-04-07T14:30:00.000Z. Lembre-se de multiplicar por 1000 porque oDatedo JavaScript espera milissegundos. No sentido inverso:Math.floor(Date.now() / 1000)dá um timestamp em segundos. - Python,
datetime.fromtimestamp(1712502600, tz=timezone.utc).isoformat()devolve2024-04-07T14:30:00+00:00. Eviteutcfromtimestamp(); devolve um datetime ingénuo que o resto do seu código tratará erradamente como hora local. - Go,
time.Unix(1712502600, 0).UTC().Format(time.RFC3339)devolve2024-04-07T14:30:00Z. O pacote time do Go é invulgar mas consistente uma vez interiorizado o layout de referênciaMon Jan 2 15:04:05 MST 2006. - Shell,
date -u -d @1712502600 +"%Y-%m-%dT%H:%M:%SZ"em GNU/Linux, oudate -u -r 1712502600 +"%Y-%m-%dT%H:%M:%SZ"em BSD/macOS. A diferença de flag é um dos pés-de-banco multiplataforma mais googlados. - Rust,
chrono::DateTime::<chrono::Utc>::from_timestamp(1712502600, 0).unwrap().to_rfc3339()devolve a mesma string ISO. A biblioteca padrão agora temSystemTimemas chrono ainda é a escolha prática para formatação. - SQL (Postgres),
SELECT to_timestamp(1712502600) AT TIME ZONE 'UTC';devolve umtimestamptz. MySQL usaFROM_UNIXTIME(); SQLite usadatetime(1712502600, 'unixepoch').
Uma ferramenta de conversão é mais rápida que qualquer um destes one-liners quando só precisa de traduzir um único valor, o que é a maior parte do tempo durante a depuração.
Porque ISO 8601 vence para armazenamento
O ISO 8601 (e o perfil RFC 3339) ordena-se corretamente como string pura. 2024-04-07T14:30:00Z vem alfabeticamente antes de 2024-04-07T15:00:00Z, que vem antes de 2024-04-08T00:00:00Z. Essa propriedade deixa-o ordenar timestamps sem os parsear, agrupar linhas de log com sort | uniq -c e raciocinar sobre intervalos com simples comparações de string.
Também é inequívoco de uma forma que os formatos regionais não são. 04/07/2024 podia ser 7 de abril (EUA) ou 4 de julho (a maioria da Europa); 2024-04-07 é o mesmo em todas as locales. Para troca máquina a máquina, essa falta de ambiguidade vale mais do que qualquer outra consideração de formatação.
Armadilhas comuns a evitar
- Esquecer o fuso horário,
2026-04-07 14:30é ambíguo sem fuso. Inclua sempreZou um offset+00:00ao armazenar strings ISO, e nunca confie no fuso por defeito do leitor. - Misturar segundos e milissegundos, um timestamp Unix de 10 dígitos está em segundos, um de 13 dígitos em milissegundos. Misturá-los produz datas em 1970 ou num futuro distante. Microssegundos (16 dígitos) e nanossegundos (19 dígitos) também aparecem, por isso antecipe-os.
- Contar com a hora local nos servidores, se o seu servidor está em UTC e o utilizador em Tóquio, armazene UTC e converta na exibição. Deixar o servidor inferir a locale leva quase sempre a bugs quando os utilizadores viajam ou o horário de verão muda.
- Parsear com aritmética de string, não corte nem concatene strings de data. Use
Date.parse(),dateutil.parser,chrono, ou a biblioteca padrão da sua linguagem. O parse manual parte-se em datas extremas, anos bissextos e offsets de fuso. - Confiar em
new Date("2024-04-07"), JavaScript parseia strings só-data como meia-noite UTC, mas strings data-hora sem fuso como meia-noite local. O comportamento difere entre browsers e versões do Node. Inclua sempre umZou offset explícito. - Anos com dois dígitos,
04/07/24podia ser 1924, 2024 ou 2124 dependendo da implementação. Use anos com quatro dígitos em todo o lado. - Transições de horário de verão, o relógio local salta uma hora na primavera e repete uma no outono. Um agendador ingénuo pode correr uma tarefa duas vezes ou nenhuma nesses dias. Use UTC para a lógica de agendamento e converta só para exibir.
- Segundos intercalares, o tempo Unix finge que não existem alisando ou repetindo o segundo afetado. Código que compara "segundos decorridos" pode divergir brevemente de um relógio de parede que respeita segundos intercalares.
- O problema do ano 2038, o
time_tassinado de 32 bits transborda a 19 de janeiro de 2038. A maioria dos sistemas modernos usa tempo de 64 bits, mas dispositivos embarcados antigos e colunas de base de dados antigas ainda podem encontrá-lo. Audite onde quer que vejaINT4ouint32usado para armazenar timestamps. - Formatação dependente de locale,
toLocaleString()em JavaScript e funções equivalentes noutras linguagens produzem saída diferente em máquinas diferentes. Para timestamps legíveis por máquina, usetoISOString()ou equivalente; para exibir, formate explicitamente.
Ferramentas e bibliotecas alternativas
Um conversor trata do caso pontual; para código de produção vai recorrer a uma biblioteca.
| Ferramenta / biblioteca | Linguagem | Força | A vigiar |
|---|---|---|---|
| Conversor web | Browser | Instantâneo, sem instalação, trata de ambiguidades comuns | Um valor de cada vez |
dateutil | Python | Parser tolerante, consciente de fusos | Mais lento que datetime para trabalho em massa |
arrow | Python | API amigável, defaults ISO | Dependência extra para projetos pequenos |
date-fns | JavaScript | Tree-shakable, imutável | Cada função é o seu próprio import |
dayjs | JavaScript | Pequeno, API compatível com moment | Modelo de plugins para extras |
luxon | JavaScript | Fusos IANA de primeira classe | Bundle maior |
chrono | Rust | Tipos ricos, RFC 3339 nativo | Ritmo de manutenção varia |
Joda-Time / java.time | Java | O design de referência que influenciou os outros | Evite os legados Date e Calendar |
NodaTime | C#/.NET | Instantes, durações e calendários bem separados | Migrar de DateTime não é trivial |
GNU date | Shell Linux | Parsing flexível com -d | BSD/macOS usa flags incompatíveis |
A biblioteca certa depende da sua stack; a disciplina certa é a mesma em todo o lado: armazene UTC, transmita ISO 8601, formate só para exibir, e nunca confie num timestamp sem fuso explícito.
Privacidade e o conversor
O conversor de formatos de tempo corre inteiramente no seu browser. Os timestamps que cola e as datas que gera nunca saem da página. Não há registo em servidor de que valores foram convertidos, nem analítica sobre que formatos são populares, nem maneira de alguém ligar um pedido ao seu IP. As conversões de tempo não são dados pessoais por si só, mas os timestamps nos seus logs (horas de login, horas de transação, janelas de agendamento) muitas vezes são, e passá-los por um conversor de terceiros podia vazar detalhes operacionais. Fazer o trabalho do lado do cliente mantém essa informação na sua máquina, onde pertence. Para uma tarefa tão rotineira como trocar entre segundos e ISO 8601, o nível de privacidade por defeito devia ser sem transmissão, sem registo, sem terceiros no circuito.
Perguntas frequentes
O que é o formato ISO 8601?
ISO 8601 é o padrão internacional de representação de data e hora. Tem a aparência 2026-04-07T14:30:00Z, onde o T separa data e hora, e o Z indica UTC. É inequívoco em qualquer região.
Por que as APIs usam timestamps Unix em vez de datas legíveis?
Os timestamps Unix são um único número, o que os torna fáceis de armazenar, ordenar e comparar. São neutros em relação ao fuso (sempre UTC) e ocupam menos espaço que strings formatadas de data. A desvantagem é que não são legíveis por humanos.
O que significa o Z no final de um timestamp?
O Z representa "hora Zulu", que é outro nome para UTC (Tempo Universal Coordenado). Um timestamp terminando em Z está em UTC, não no horário local.
Como converto 24 horas para 12 horas?
Para horas de 1 a 12, a hora continua igual (adicione AM para 0-11, PM para 12). Para horas de 13 a 23, subtraia 12 e adicione PM. 00:00 é 12:00 AM (meia-noite). 12:00 é 12:00 PM (meio-dia).
What is the Year 2038 problem?
32-bit signed Unix timestamps overflow on 19 January 2038 at 03:14:07 UTC, after which they wrap around to negative values that look like dates in 1901. Most modern systems use 64-bit timestamps and are unaffected, but legacy embedded devices, old databases, and 32-bit time_t in some C code still need to be audited.
How are leap seconds handled in Unix time?
Unix time pretends leap seconds do not exist. The clock simply repeats or stretches the affected second, so a Unix timestamp is not a strict count of elapsed SI seconds. For most applications this is fine, but precision-timing code (astronomy, GPS, high-frequency trading) needs TAI or UTC with explicit leap-second handling.