Guide

Umgang mit Schaltsekunden

Einführung

Schaltsekunden sind gelegentliche Anpassungen der koordinierten Weltzeit (UTC) um jeweils eine Sekunde, um sie mit der Erdrotation synchron zu halten. Sie stellen einen der komplexesten Aspekte des Zeitmanagements in der Softwareentwicklung dar.

Kurze Zusammenfassung: UTC fügt Schaltsekunden hinzu, um innerhalb von 0,9 Sekunden von UT1 (Sonnenzeit) zu bleiben. Seit Januar 2026 wurden seit 1972 37 Schaltsekunden hinzugefügt, sodass UTC 37 Sekunden hinter der Internationalen Atomzeit (TAI) liegt.

Was sind Schaltsekunden?

Definition

Eine Schaltsekunde ist eine auf UTC angewendete Anpassung von einer Sekunde, um Folgendes zu berücksichtigen:

  1. Die Rotation der Erde verlangsamt sich: Die Rotation der Erde verlangsamt sich allmählich
  2. Unregelmäßige Rotationsgeschwindigkeit: Die Rotationsgeschwindigkeit der Erde variiert unvorhersehbar
  3. UT1-UTC-Divergenz: UTC innerhalb von ±0,9 Sekunden der Sonnenzeit (UT1) halten
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

Wie Schaltsekunden funktionieren

Wenn eine Schaltsekunde hinzugefügt wird, hat die letzte Minute eines UTC-Tages 61 Sekunden statt 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)

Hinweis: Negative Schaltsekunden sind in der Praxis nie aufgetreten, obwohl sie theoretisch möglich sind, wenn sich die Erdrotation plötzlich beschleunigt.

Geschichte der Schaltsekunden

Zeitleiste

JahrVeranstaltungUTC-TAI-Offset
1972Erste Schaltsekunde hinzugefügt+10 Sekunden
1972-198412 Schaltsekunden hinzugefügt+22 Sekunden
1985-19958 Schaltsekunden hinzugefügt+29 Sekunden
1996-20053 Schaltsekunden hinzugefügt+32 Sekunden
2008-20163 Schaltsekunden hinzugefügt+35 Sekunden
2017Letzte Schaltsekunde+36 Sekunden
2025Zukünftige Schaltsekunde+37 Sekunden

Aktuelle Schaltsekunden

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)

Zukunft der Schaltsekunden

Die Internationale Fernmeldeunion (ITU) erwägt, die Schaltsekunden bis 2035 abzuschaffen, was die Zeiterfassung weltweit vereinfachen würde.

Wichtig: Wenn die Schaltsekunden abgeschafft würden, würde die UTC allmählich von der Sonnenzeit abweichen. Dies ist ein kontroverses Thema unter Astronomen, Softwareentwicklern und Zeitmessorganisationen.

TAI vs. UTC

Internationale Atomzeit (TAI)

TAI ist eine Zeitskala, die auf dem gewichteten Durchschnitt der Atomuhren weltweit basiert. Es enthält keine Schaltsekunden, sodass es sich um eine vollkommen einheitliche Zeitskala handelt.

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)

Konvertierung zwischen TAI und 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}')

Umgang mit Schaltsekunden in der Programmierung

JavaScript

Das Date-Objekt von JavaScript unterstützt Schaltsekunden nicht direkt. Der Zeitstempel 23:59:60 wird als 23:59:59 wiederholt.

// 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

Python

Das datetime-Modul von Python bietet nur begrenzte Unterstützung für Schaltsekunden. Die Standardbibliothek repräsentiert nicht 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

Das Java 8+ java.time-Paket unterstützt Schaltsekunden in der Instant-Klasse.

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);

Los

Das time-Paket von Go bietet keine native Schaltsekundenunterstützung.

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
    }
}

Zeitverschmierung

Was ist Time Smearing?

Time Smearing ist eine Technik, um Schaltsekundenanpassungen schrittweise über einen Zeitraum (normalerweise 12–24 Stunden) zu verteilen, anstatt sie sofort anzuwenden.

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

Verleumderische Implementierungen

SystemVerschmiermethodeDauer
Google TrueTimeLinearer Abstrich24 Stunden
Amazon Time Sync ServiceLinearer Abstrich24 Stunden
NTP-PoolsOptionaler Abstrich1-24 Stunden
LinuxKernel-Schritt (kein Smear)Sofort

Hinweis: Time Smearing wird von großen verteilten Systemen verwendet, um Synchronisierungsprobleme zu vermeiden. Dies führt jedoch zu eigenen Problemen: Die verschwommene Zeit entspricht nicht der Standard-UTC und kann nicht zuverlässig in andere Zeitsysteme konvertiert werden.

IETF RFC 8536-Empfehlungen

RFC 8536 bietet Richtlinien für die Handhabung von Schaltsekunden in Softwaresystemen:

Wichtige Empfehlungen

  1. TAI für interne Zeit verwenden: Speichern Sie TAI-Zeitstempel aus Präzisionsgründen intern
  2. Nur zur Anzeige in UTC konvertieren: Wenden Sie den Schaltsekunden-Offset nur bei der Anzeige für Benutzer an
  3. NTP zur Synchronisierung verwenden: Erhalten Sie die genaue Uhrzeit von NTP-Servern
  4. Schaltsekundenhandhabung dokumentieren: Dokumentieren Sie klar und deutlich, wie Ihr System mit Schaltsekunden umgeht
  5. Schaltsekundenereignisse testen: Simulieren Sie Schaltsekundenübergänge in Ihren Tests

Best Practices

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

Häufige Probleme und Lösungen

Problem 1: Zeitsprünge während der Schaltsekunde

Problem: Systeme erleben während des Schaltsekundenübergangs einen 1-Sekunden-Sprung.

Lösung: Nutzen Sie Time Smearing oder implementieren Sie das Bewusstsein für Schaltsekunden.

// 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
}

Problem 2: Datenbankabfragefehler

Problem: Abfragen schlagen während der Schaltsekunde fehl, da Zeitstempel wie 23:59:60 in den meisten Datenbanken ungültig sind.

Lösung: Zeitstempel ohne Schaltsekunden speichern, Schaltsekundenverhalten dokumentieren.

-- 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';

Problem 3: Protokollierungsfehler während der Schaltsekunde

Problem: Protokolldateien zeigen während der Schaltsekunde doppelte oder nicht in der Reihenfolge liegende Zeitstempel.

Lösung: Verwenden Sie hochauflösende Zeitstempel und eindeutige Sequenzkennungen.

# 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}')

Codebeispiele nach Szenario

Szenario 1: Konvertieren von Zeitstempeln mit Schaltsekunden-Offset

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"

Szenario 2: Überprüfen, ob es sich bei einem Datum um eine Schaltsekunde handelt

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

Testen der Handhabung von Schaltsekunden

Testfälle

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

Best Practices-Zusammenfassung

Für die meisten Anwendungen

  1. Schaltsekunden ignorieren im Speicher (Standard-UTC-Zeitstempel verwenden)
  2. Dokumentieren Sie Ihre Richtlinie zur Handhabung von Schaltsekunden
  3. Test mit historischen Schaltsekundendaten
  4. Verwenden Sie UTC als primären Zeitstandard

Für hochpräzise Anwendungen

  1. TAI-Zeitstempel speichern für interne Berechnungen
  2. Schaltsekundentabelle pflegen für Konvertierungen
  3. NTP für die Synchronisierung verwenden
  4. Implementieren Sie die Erkennung von Schaltsekunden in kritischen Codepfaden

Verwandte Tools

FAQ

F: Wie oft kommen Schaltsekunden vor?

A: Schaltsekunden sind seit 1972 27 Mal aufgetreten (etwa alle 1-2 Jahre), aber die Häufigkeit ist in letzter Zeit aufgrund der langsameren Erdrotation zurückgegangen.

F: Bleiben Schaltsekunden ewig bestehen?

A: Die ITU diskutiert über die Abschaffung von Schaltsekunden bis 2035, was deren Hinzufügung verhindern würde, aber dazu führen würde, dass UTC allmählich von der Sonnenzeit abweicht.

F: Muss ich in meiner Anwendung Schaltsekunden verarbeiten?

A: Für die meisten Anwendungen nein – verwenden Sie Standard-UTC-Zeitstempel. Behandeln Sie Schaltsekunden nur, wenn Sie zeitkritische Systeme, wissenschaftliche Anwendungen oder verteilte Datenbanken erstellen.

F: Was passiert während einer Schaltsekunde?

A: UTC fügt eine zusätzliche Sekunde hinzu (23:59:60), um mit der Erdrotation synchronisiert zu bleiben. Die meisten Systeme wiederholen 23:59:59 oder verwenden Zeitschmierung, um Sprünge zu vermeiden.

F: Wie teste ich die Handhabung von Schaltsekunden?

A: Testen Sie mit historischen Schaltsekundendaten wie 2016-12-31T23:59:60Z und stellen Sie sicher, dass Ihre Anwendung nicht abstürzt oder falsche Ergebnisse liefert.