Guide
Carimbos de data e hora em logs: análise, normalização e correção de erros
Por que esta página
Os logs chegam com formatos, fusos horários e precisão mistos. Um carimbo de data e hora incorreto interrompe pedidos, painéis e cronogramas de incidentes. Este guia fornece verificações rápidas, modelos de regex e trechos de linguagem para normalizar rapidamente os tempos de log - e indica conversores quando você precisar verificar casos extremos.
Lista de verificação de diagnóstico rápido
- Identifique formato: ISO 8601/RFC 3339, Apache/Nginx (
[dd/Mon/yyyy:HH:mm:ss Z]), syslog (MMM d HH:mm:ss) ou personalizado. - Verifique fuso horário: deslocamento explícito (
+0800,Z) vs. local implícito. O padrão é UTC se estiver ausente. - Verifique a precisão: segundos vs. milissegundos vs. microssegundos; garantir comprimento consistente.
- Lidar com bordas DST: analisar primeiro em UTC; evite análise local ingênua.
- Aplicar guardas de campo: rejeitar anos implausíveis (por exemplo,
<2000ou>2100).
Formatos de log comuns (modelos)
- ISO 8601/RFC 3339:
2024-12-01T10:15:30Z,2024-12-01T18:15:30+08:00 - Apache/Nginx:
[01/dez/2024:10:15:30 +0000] - Syslog:
1º de dezembro 10:15:30 hostname app[123]: mensagem(sem ano/deslocamento) - Número personalizado:
1701425730(segundos),1701425730000(ms)
Etapas de normalização
- Detecte formato e fuso horário. Se estiver faltando, assuma UTC.
- Analise em uma data e hora consciente (UTC).
- Se época numérica: escala por duração (10s/13ms/16µs/19ns).
- Armazene em uma coluna canônica (por exemplo, milis UTC) e, opcionalmente, mantenha a string bruta.
- Validar intervalo; elimine ou sinalize valores discrepantes antes da indexação.
Trechos de código
###JavaScript/Node.js
import { DateTime } from "luxon";
export function parseLogTime(raw) {
const trimmed = raw.trim();
// ISO/RFC first
const iso = DateTime.fromISO(trimmed, { setZone: true });
if (iso.isValid) return iso.toUTC().toMillis();
// Apache/Nginx: [01/Dec/2024:10:15:30 +0000]
const m = trimmed.match(/\\[(\\d{2}\\/\\w{3}\\/\\d{4}:\\d{2}:\\d{2}:\\d{2} [+-]\\d{4})\\]/);
if (m) {
const dt = DateTime.fromFormat(m[1], "dd/MMM/yyyy:HH:mm:ss ZZZZ", { zone: "utc" });
if (dt.isValid) return dt.toMillis();
}
// Numeric epoch (seconds/ms/us/ns)
if (/^\\d+$/.test(trimmed)) {
const len = trimmed.length;
if (len === 10) return Number(trimmed) * 1000;
if (len === 13) return Number(trimmed);
if (len === 16) return Number(trimmed) / 1000;
if (len === 19) return Number(trimmed) / 1_000_000;
}
throw new Error("Unrecognized log timestamp");
}
###Píton
from datetime import datetime, timezone, timedelta
from dateutil import parser
def parse_log_time(raw: str) -> int:
s = raw.strip()
# ISO/RFC 3339, syslog with tz, etc.
try:
dt = parser.isoparse(s)
if dt.tzinfo is None:
dt = dt.replace(tzinfo=timezone.utc)
return int(dt.astimezone(timezone.utc).timestamp() * 1000)
except Exception:
pass
# Apache/Nginx like: [01/Dec/2024:10:15:30 +0000]
if s.startswith("[") and s.endswith("]"):
inner = s[1:-1]
dt = datetime.strptime(inner, "%d/%b/%Y:%H:%M:%S %z")
return int(dt.astimezone(timezone.utc).timestamp() * 1000)
# Numeric epoch
if s.isdigit():
n = len(s)
if n == 10:
return int(s) * 1000
if n == 13:
return int(s)
if n == 16:
return int(int(s) / 1000)
if n == 19:
return int(int(s) / 1_000_000)
raise ValueError("Unrecognized log timestamp")
Modelos Regex
regex
# ISO 8601 / RFC 3339 with offset
^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:?\\d{2})$
# Apache/Nginx
^\\[\\d{2}/[A-Za-z]{3}/\\d{4}:\\d{2}:\\d{2}:\\d{2} [+-]\\d{4}\\]$
# Syslog (no year/offset, add externally)
^[A-Za-z]{3}\\s+\\d{1,2}\\s\\d{2}:\\d{2}:\\d{2}\\s.+$
Ordenação, indexação e armazenamento
- Normalize para milissegundos UTC (ou superior) antes do armazenamento; mantenha o texto bruto se precisar analisar novamente.
- Use filtros de intervalo (
WHERE ocorreu_at_ms >= ... AND ocorreu_at_ms < ...) para manter a indexação amigável. - Se a ingestão misturar formatos, adicione uma coluna validated_at e coloque falhas em quarentena.
- Particionamento por data para logs de alto volume; evite lançar em filtros.
Armadilhas comuns (e soluções)
- Fuso horário ausente: padrão é UTC; o analisador de log deve adicionar o fuso horário do host de origem, se conhecido.
- Intervalos/sobreposições de horário de verão: analise primeiro como UTC; localize apenas ao exibir.
- Precisão mista: segundos e milissegundos misturados em uma coluna; impor comprimento na ingestão.
- Syslog ano ausente: anexe o ano atual durante a análise e valide o intervalo.
- Filtros agrupados por função: evite
DATE(occurred_at)em WHERE; use colunas de data geradas.
Perguntas frequentes
- Como detectar milissegundos versus segundos? Verifique o comprimento dos dígitos: 10=segundos, 13=ms, 16=µs, 19=ns.
- E se o fuso horário estiver faltando? Suponha o UTC ou injete o fuso horário do host conhecido antes de analisar.
- Por que os painéis estão fora de ordem? Provavelmente precisão mista ou classificação de strings; normalize para UTC numérico e índice.
- Como limpar logs históricos em lote? Use uma tabela intermediária, analise + valide e mova apenas linhas limpas; veja ferramentas relacionadas.
Ferramentas e guias relacionados
- Conversor de carimbo de data/hora Unix
- [Conversor de carimbo de data e hora em lote](/conversor de carimbo de data e hora em lote)
- Construtor de formato de carimbo de data/hora
- Solução de problemas de carimbo de data/hora inválido
- Níveis de precisão do carimbo de data/hora
- Compreendendo os fusos horários