Guide

Lidando com segundos bissextos

Introdução

Os segundos bissextos são ajustes ocasionais de um segundo no Tempo Universal Coordenado (UTC) para mantê-lo sincronizado com a rotação da Terra. Eles representam um dos aspectos mais complexos do gerenciamento de tempo no desenvolvimento de software.

Resumo rápido: UTC adiciona segundos bissextos para ficar dentro de 0,9 segundos do UT1 (hora solar). Em janeiro de 2026, 37 segundos bissextos foram adicionados desde 1972, tornando o UTC 37 segundos atrás do Tempo Atômico Internacional (TAI).

O que são segundos bissextos?

Definição

Um segundo bissexto é um ajuste de um segundo aplicado ao UTC para contabilizar:

  1. Rotação em desaceleração da Terra: A rotação da Terra está desacelerando gradualmente
  2. Taxa de rotação irregular: a velocidade de rotação da Terra varia de forma imprevisível
  3. Divergência UT1-UTC: Manter o UTC dentro de ±0,9 segundos da hora solar (UT1)
Leap Second Formula:
  If UT1 - UTC > 0.9 seconds → Add positive leap second
  If UT1 - UTC < -0.9 seconds → Add negative leap second

Result: UTC stays synchronized with Earth's rotation

Como funcionam os segundos bissextos

Quando um segundo bissexto é adicionado, o último minuto de um dia UTC tem 61 segundos em vez de 60:

Normal Day (no leap second):
  23:59:58 UTC
  23:59:59 UTC
  00:00:00 UTC (next day)

Leap Second Day:
  23:59:58 UTC
  23:59:59 UTC
  23:59:60 UTC  ← Leap second!
  00:00:00 UTC (next day)

Nota: Segundos bissextos negativos nunca ocorreram na prática, embora sejam teoricamente possíveis se a rotação da Terra acelerar repentinamente.

História dos segundos bissextos

Linha do tempo

AnoEventoCompensação UTC-TAI
1972Primeiro salto segundo adicionado+10 segundos
1972-198412 segundos bissextos adicionados+22 segundos
1985-19958 segundos bissextos adicionados+29 segundos
1996-20053 segundos bissextos adicionados+32 segundos
2008-20163 segundos bissextos adicionados+35 segundos
2017Último segundo bissexto+36 segundos
2025Segundo salto futuro+37 segundos

Segundos bissextos recentes

All Leap Seconds (1972 - 2025):
  - 1972-06-30: +1 second (UTC-TAI = +11s)
  - 1972-12-31: +1 second (UTC-TAI = +12s)
  - 1973-12-31: +1 second (UTC-TAI = +13s)
  - 1974-12-31: +1 second (UTC-TAI = +14s)
  - 1975-12-31: +1 second (UTC-TAI = +15s)
  - 1976-12-31: +1 second (UTC-TAI = +16s)
  - 1977-12-31: +1 second (UTC-TAI = +17s)
  - 1978-12-31: +1 second (UTC-TAI = +18s)
  - 1979-12-31: +1 second (UTC-TAI = +19s)
  - 1981-06-30: +1 second (UTC-TAI = +20s)
  - 1982-06-30: +1 second (UTC-TAI = +21s)
  - 1983-06-30: +1 second (UTC-TAI = +22s)
  - 1985-06-30: +1 second (UTC-TAI = +23s)
  - 1987-12-31: +1 second (UTC-TAI = +24s)
  - 1988-12-31: +1 second (UTC-TAI = +25s)
  - 1989-12-31: +1 second (UTC-TAI = +26s)
  - 1990-12-31: +1 second (UTC-TAI = +27s)
  - 1992-06-30: +1 second (UTC-TAI = +28s)
  - 1993-06-30: +1 second (UTC-TAI = +29s)
  - 1994-06-30: +1 second (UTC-TAI = +30s)
  - 1995-12-31 +1 second (UTC-TAI = +31s)
  - 1997-12-31 +1 second (UTC-TAI = +32s)
  - 1998-12-31 +1 second (UTC-TAI = +33s)
  - 1999-12-31 +1 second (UTC-TAI = +34s)
  - 2000-12-31 +1 second (UTC-TAI = +35s)
  - 2005-12-31 +1 second (UTC-TAI = +36s)
  - 2008-12-31: +1 second (UTC-TAI = +37s)

Futuro dos segundos bissextos

A União Internacional de Telecomunicações (UIT) está a considerar abolir os segundos bissextos até 2035, o que simplificaria o tratamento do tempo em todo o mundo.

Importante: Se os segundos bissextos fossem abolidos, o UTC divergiria gradualmente da hora solar. Este é um tema controverso entre astrônomos, desenvolvedores de software e organizações de cronometragem.

##TAI x UTC

Hora Atômica Internacional (TAI)

TAI é uma escala de tempo baseada na média ponderada dos relógios atômicos em todo o mundo. Nunca inclui segundos bissextos, tornando-se uma escala de tempo perfeitamente uniforme.

TAI Characteristics:
  - Based on: 400+ atomic clocks worldwide
  - Precision: ±0.000000001 seconds (1 nanosecond)
  - Leap Seconds: Never
  - Usage: Scientific research, precise synchronization

Current TAI-UTC Offset: +37 seconds (as of January 2026)

Conversão entre TAI e UTC

// Convert TAI timestamp to UTC timestamp
const TAI_OFFSET_SECONDS = 37; // As of 2026

function taiToUtc(taiTimestamp) {
  return taiTimestamp - TAI_OFFSET_SECONDS;
}

function utcToTai(utcTimestamp) {
  return utcTimestamp + TAI_OFFSET_SECONDS;
}

// Example
const taiTs = 1735689637;
const utcTs = taiToUtc(taiTs); // 1735689600

console.log('TAI Timestamp:', taiTs);
console.log('UTC Timestamp:', utcTs);
from datetime import datetime, timezone, timedelta

TAI_OFFSET_SECONDS = 37  # As of 2026

def tai_to_utc(tai_timestamp):
    return tai_timestamp - TAI_OFFSET_SECONDS

def utc_to_tai(utc_timestamp):
    return utc_timestamp + TAI_OFFSET_SECONDS

# Example
tai_ts = 1735689637
utc_ts = tai_to_utc(tai_ts)  # 1735689600

print(f'TAI Timestamp: {tai_ts}')
print(f'UTC Timestamp: {utc_ts}')

Lidando com segundos bissextos na programação

JavaScript

O objeto Date do JavaScript não suporta segundos bissextos diretamente. Ele repete o carimbo de data/hora 23:59:60 como 23:59:59.

// Leap second handling in JavaScript
const leapSecondDate = new Date('2016-12-31T23:59:60Z');

// JavaScript treats this as 23:59:59Z
console.log(leapSecondDate.toISOString()); // "2016-12-31T23:59:59.000Z"

// Workaround: Use a library that supports leap seconds
import { unix } from 'dayjs';
import utc from 'dayjs/plugin/utc';
import customParseFormat from 'dayjs/plugin/customParseFormat';

// Note: Day.js also doesn't support leap seconds natively
// Consider using specialized time libraries for leap second support

###Píton

O módulo datetime do Python tem suporte limitado para segundos bissextos. A biblioteca padrão não representa 23:59:60.

# Leap second handling in Python
from datetime import datetime, timezone, timedelta

# Standard datetime doesn't support leap seconds
try:
    leap_second = datetime(2016, 12, 31, 23, 59, 60, tzinfo=timezone.utc)
except ValueError as e:
    print(f'Error: {e}')  # ValueError: second must be in 0..59

# Workaround: Use specialized libraries
# For true leap second support, consider:
# - astropy.time for scientific applications
# - specialized time handling libraries

###Java

O pacote Java 8+ java.time suporta segundos bissextos na classe Instant.

import java.time.Instant;
import java.time.temporal.ChronoUnit;

// Leap second handling in Java
Instant leapSecondInstant = Instant.parse("2016-12-31T23:59:60Z");

// Java correctly handles leap second in Instant
System.out.println("Leap Second: " + leapSecondInstant);

// Check if a timestamp contains a leap second
Instant timestamp = Instant.parse("2016-12-31T23:59:60Z");
boolean isLeapSecond = timestamp.getNano() == 0 &&
                       timestamp.getEpochSecond() % 60 == 59;

System.out.println("Is Leap Second: " + isLeapSecond);

O pacote time do Go não tem suporte nativo para segundos bissextos.

package main

import (
    "fmt"
    "time"
)

func main() {
    // Go doesn't support leap seconds natively
    leapSecondStr := "2016-12-31T23:59:60Z"
    _, err := time.Parse(time.RFC3339, leapSecondStr)

    if err != nil {
        fmt.Println("Error:", err)
        // Go will reject leap second timestamps
    }
}

Mancha de tempo

O que é mancha de tempo?

Mancha de tempo é uma técnica para distribuir gradualmente ajustes de segundos intercalados ao longo de um período (geralmente de 12 a 24 horas), em vez de aplicá-los instantaneamente.

Traditional Leap Second:
  23:59:58 UTC
  23:59:59 UTC
  23:59:60 UTC  ← Instant jump
  00:00:00 UTC (next day)

Smeared Leap Second (24-hour smear):
  Each second is ~1.16ms longer for 24 hours
  No instant jump, smooth transition

Implementações de manchas

SistemaMétodo de manchaDuração
Google TrueTimeEsfregaço linear24 horas
Serviço Amazon Time SyncEsfregaço linear24 horas
Conjuntos NTPEsfregaço opcional1-24 horas
LinuxEtapa do kernel (sem esfregaço)Instantâneo

Observação: A dispersão de tempo é usada por grandes sistemas distribuídos para evitar problemas de sincronização. No entanto, ele cria seus próprios problemas: o tempo manchado não é o UTC padrão e não pode ser convertido de forma confiável para outros sistemas de horário.

Recomendações IETF RFC 8536

RFC 8536 fornece diretrizes para manipulação de segundos bissextos em sistemas de software:

Principais recomendações

  1. Use TAI para horário interno: armazene carimbos de data/hora TAI internamente para precisão
  2. Converter para UTC somente para exibição: aplique deslocamento de segundo intercalado somente ao exibir para usuários
  3. Use NTP para sincronização: obtenha tempo preciso de servidores NTP
  4. Documente o tratamento de segundos bissextos: documente claramente como seu sistema lida com segundos bissextos
  5. Teste eventos de segundos bissextos: simule transições de segundos bissextos em seus testes

Melhores Práticas

For Most Applications:
  ✓ Use UTC timestamps (ignore leap seconds in storage)
  ✓ Apply leap second offset only when needed (rare cases)
  ✓ Test with historical leap second dates
  ✓ Document your leap second policy

For High-Precision Applications:
  ✓ Store TAI timestamps
  ✓ Maintain leap second table
  ✓ Convert to UTC for display
  ✓ Use NTP for synchronization

Problemas e soluções comuns

Edição 1: O tempo salta durante o segundo bissexto

Problema: Os sistemas experimentam um salto de 1 segundo durante a transição do segundo bissexto.

Solução: use a dispersão do tempo ou implemente a percepção do segundo bissexto.

// Time smearing example (simplified)
function smearedTime(timestamp, leapSecondDate) {
  const diffHours = (timestamp - leapSecondDate) / (1000 * 60 * 60);
  const smearDuration = 24; // 24 hours
  const smearFactor = Math.min(Math.max(diffHours / smearDuration, 0), 1);

  return timestamp + smearFactor * 1000; // Add up to 1 second over 24 hours
}

Problema 2: Falhas na consulta do banco de dados

Problema: as consultas falham durante o segundo bissexto porque carimbos de data/hora como 23:59:60 são inválidos na maioria dos bancos de dados.

Solução: armazene carimbos de data/hora sem segundos bissextos e documente o comportamento dos segundos bissextos.

-- Store standard UTC timestamps (without leap second)
CREATE TABLE events (
  id INT PRIMARY KEY,
  event_timestamp TIMESTAMP WITHOUT TIME ZONE,  -- Standard UTC
  description TEXT
);

-- Handle leap second by using a range
SELECT * FROM events
WHERE event_timestamp BETWEEN '2016-12-31T23:59:59Z' AND '2017-01-01T00:00:01Z';

Problema 3: Registro de erros durante o segundo bissexto

Problema: os arquivos de log mostram carimbos de data/hora duplicados ou fora de ordem durante o segundo bissexto.

Solução: use carimbos de data/hora de alta resolução e identificadores de sequência exclusivos.

# Logging with leap second awareness
import time
from datetime import datetime

def log_event(message):
    # Use millisecond precision to handle leap seconds
    timestamp = datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
    sequence_id = time.time_ns()  # Nanosecond precision

    print(f'[{timestamp}] [{sequence_id}] {message}')

Exemplos de código por cenário

Cenário 1: Convertendo carimbos de data/hora com deslocamento de segundo bissexto

const LEAP_SECONDS = 37; // As of 2026

// Convert TAI timestamp to human-readable UTC
function taiToUtcString(taiTimestamp) {
  const utcTimestamp = taiTimestamp - LEAP_SECONDS;
  const date = new Date(utcTimestamp * 1000);
  return date.toISOString();
}

// Example
const taiTs = 1735689637;
console.log(taiToUtcString(taiTs)); // "2026-01-01T00:00:00.000Z"
from datetime import datetime, timezone, timedelta

LEAP_SECONDS = 37  # As of 2026

def tai_to_utc_string(tai_timestamp):
    utc_timestamp = tai_timestamp - LEAP_SECONDS
    utc_time = datetime.fromtimestamp(utc_timestamp, timezone.utc)
    return utc_time.isoformat()

# Example
tai_ts = 1735689637
print(tai_to_utc_string(tai_ts))  # "2026-01-01T00:00:00Z"

Cenário 2: Verificando se uma data é um segundo bissexto

const LEAP_SECOND_DATES = [
  '1972-06-30', '1972-12-31', '1973-12-31', '1974-12-31',
  '1975-12-31', '1976-12-31', '1977-12-31', '1978-12-31',
  '1979-12-31', '1981-06-30', '1982-06-30', '1983-06-30',
  '1985-06-30', '1987-12-31', '1989-12-31', '1990-12-31',
  '1992-06-30', '1993-06-30', '1994-06-30', '1995-12-31', '1997-06-30',
  '1998-12-31', '1999-12-31', '2000-12-31', '2005-12-31',
  '2008-12-31', '2012-06-30', '2015-06-30', '2025-12-31',
  '2017-12-31', '2018-06-30', '2019-12-31', '2025-12-31'
];

function isLeapSecondDate(date) {
  const dateStr = date.toISOString().split('T')[0];
  return LEAP_SECOND_DATES.includes(dateStr);
}

// Example
const date = new Date('2016-12-31T23:59:59Z');
console.log(isLeapSecondDate(date)); // true
from datetime import datetime

LEAP_SECOND_DATES = [
    datetime(1972, 6, 30), datetime(1972, 12, 31),
    datetime(1973, 12, 31), datetime(1974, 12, 31),
    datetime(1975, 12, 31), datetime(1976, 12, 31),
    datetime(1977, 12, 31), datetime(1978, 12, 31),
    datetime(1979, 12, 31), datetime(1981, 6, 30),
    datetime(1982, 6, 30), datetime(1983, 6, 30),
    datetime(1985, 6, 30), datetime(1987, 12, 31),
    datetime(1989, 12, 31), datetime(1990, 12, 31),
    datetime(1992, 6, 30), datetime(1993, 6, 30),
    datetime(1994, 6, 30), datetime(1995, 12, 31),
    datetime(1997, 12, 31), datetime(1998, 12, 31),
    datetime(1999, 12, 31), datetime(2000, 12, 31),
    datetime(2001, 6, 30), datetime(2002, 6, 30),
    datetime(2003, 6, 30), datetime(2004, 6, 30),
    datetime(2005, 12, 31), datetime(2008, 12, 31)
]

def is_leap_second_date(date):
    return any(
        date.year == leap_date.year and
        date.month == leap_date.month and
        date.day == leap_date.day
        for leap_date in LEAP_SECOND_DATES
    )

# Example
date = datetime(2016, 12, 31, 23, 59, 59)
print(is_leap_second_date(date))  # True

Testando o manuseio do segundo bissexto

Casos de teste

Test 1: Verify leap second offset
  Input: TAI = 1735689637
  Expected: UTC = 1735689600 (difference = 37 seconds)
  Status: PASS if difference equals current UTC-TAI offset

Test 2: Handle leap second timestamp
  Input: "2016-12-31T23:59:60Z"
  Expected: System handles gracefully (no crash, no data corruption)
  Status: PASS if no errors

Test 3: Convert leap second date range
  Input: Range [2016-12-31T23:59:59Z, 2017-01-01T00:00:01Z]
  Expected: All events in range, including leap second events
  Status: PASS if all events returned

Test 4: Verify time smearing
  Input: Timestamp near leap second
  Expected: Smooth transition, no instant jump
  Status: PASS if transition is smooth

Resumo das melhores práticas

Para a maioria das aplicações

  1. Ignore segundos bissextos no armazenamento (use carimbos de data/hora UTC padrão)
  2. Documente sua política de manuseio do segundo bissexto
  3. Teste com datas históricas de segundos bissextos
  4. Use UTC como seu padrão de horário principal

Para aplicações de alta precisão

  1. Armazene carimbos de data/hora TAI para cálculos internos
  2. Mantenha a tabela do segundo bissexto para conversões
  3. Use NTP para sincronização
  4. Implemente o reconhecimento do segundo bissexto em caminhos de código críticos

Ferramentas relacionadas

Perguntas frequentes

P: Com que frequência ocorrem segundos bissextos?

R: Os segundos bissextos ocorreram 27 vezes desde 1972 (cerca de uma vez a cada 1-2 anos), mas a frequência diminuiu recentemente devido à desaceleração da rotação da Terra.

P: Os segundos bissextos continuarão para sempre?

R: A UIT está discutindo a abolição dos segundos bissextos até 2035, o que impediria sua adição, mas faria com que o UTC divergisse gradualmente da hora solar.

P: Preciso lidar com segundos bissextos em meu aplicativo?

R: Para a maioria dos aplicativos, não use carimbos de data/hora UTC padrão. Lide com segundos bissextos apenas se você estiver construindo sistemas de tempo crítico, aplicativos científicos ou bancos de dados distribuídos.

P: O que acontece durante um segundo bissexto?

R: O UTC adiciona um segundo extra (23:59:60) para manter a sincronização com a rotação da Terra. A maioria dos sistemas repete 23:59:59 ou usa dispersão de tempo para evitar saltos.

P: Como faço para testar o manuseio de segundos intercalados?

R: Teste com datas históricas de segundos bissextos, como 31/12/2016T23:59:60Z e verifique se seu aplicativo não trava ou produz resultados incorretos.