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:
- Die Rotation der Erde verlangsamt sich: Die Rotation der Erde verlangsamt sich allmählich
- Unregelmäßige Rotationsgeschwindigkeit: Die Rotationsgeschwindigkeit der Erde variiert unvorhersehbar
- 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
| Jahr | Veranstaltung | UTC-TAI-Offset |
|---|---|---|
| 1972 | Erste Schaltsekunde hinzugefügt | +10 Sekunden |
| 1972-1984 | 12 Schaltsekunden hinzugefügt | +22 Sekunden |
| 1985-1995 | 8 Schaltsekunden hinzugefügt | +29 Sekunden |
| 1996-2005 | 3 Schaltsekunden hinzugefügt | +32 Sekunden |
| 2008-2016 | 3 Schaltsekunden hinzugefügt | +35 Sekunden |
| 2017 | Letzte Schaltsekunde | +36 Sekunden |
| 2025 | Zukü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
| System | Verschmiermethode | Dauer |
|---|---|---|
| Google TrueTime | Linearer Abstrich | 24 Stunden |
| Amazon Time Sync Service | Linearer Abstrich | 24 Stunden |
| NTP-Pools | Optionaler Abstrich | 1-24 Stunden |
| Linux | Kernel-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
- TAI für interne Zeit verwenden: Speichern Sie TAI-Zeitstempel aus Präzisionsgründen intern
- Nur zur Anzeige in UTC konvertieren: Wenden Sie den Schaltsekunden-Offset nur bei der Anzeige für Benutzer an
- NTP zur Synchronisierung verwenden: Erhalten Sie die genaue Uhrzeit von NTP-Servern
- Schaltsekundenhandhabung dokumentieren: Dokumentieren Sie klar und deutlich, wie Ihr System mit Schaltsekunden umgeht
- 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
- Schaltsekunden ignorieren im Speicher (Standard-UTC-Zeitstempel verwenden)
- Dokumentieren Sie Ihre Richtlinie zur Handhabung von Schaltsekunden
- Test mit historischen Schaltsekundendaten
- Verwenden Sie UTC als primären Zeitstandard
Für hochpräzise Anwendungen
- TAI-Zeitstempel speichern für interne Berechnungen
- Schaltsekundentabelle pflegen für Konvertierungen
- NTP für die Synchronisierung verwenden
- Implementieren Sie die Erkennung von Schaltsekunden in kritischen Codepfaden
Verwandte Tools
- TAI-Zeitkonverter – Konvertieren Sie zwischen TAI-, UTC- und GPS-Zeit
- Aktueller Zeitstempel – Erhalten Sie die aktuelle UTC-Zeit mit Präzision
- Unix-Zeitstempelkonverter – Behandelt verschiedene Zeitstempelgenauigkeiten
- GPS-Zeitkonverter – GPS-Zeit mit Schaltsekundenverarbeitung
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.