Post by Peter J. HolzerAuf POSIX-kompatiblen Betriebssystemen ist 23:59:60 nicht abbildbar.
2016-12-31T23:59:59Z war 1483228799 und 2017-01-01T00:00:00Z war
1483228800. Dazwischen ist kein Platz für eine weitere Sekunde. Das mag
man den Erfindern von Unix anlasten, die Mitte der 1970er-Jahre nicht
bemerkt haben, dass jedes Jahr eine Sekunde zu lang war (oder das für
vernachlässigbar hielten) oder den Machern von POSIX, die das 1988 nicht
korrigierten (aber da gab es halt schon ziemlich viele Unix-Systeme),
aber jedenfalls kann man das nicht mehr ändern.
1) Man ignoriert das Problem. Dann stellt man bei der ersten
Zeitsynchronisation nach der Schaltsekunde fest, dass die Uhr eine
Sekunde vorgeht und stellt sie zurück. Entweder sprunghaft oder
kontinuierlich über einen längeren Zeitraum. Vorteil: Einfach.
Nachteil: In einem Netzwerk wird jeder Computer zu einem anderen
Zeitpunkt feststellen, dass die Uhr falsch geht und man hat dann ein
paar Minuten bis ein paar Stunden lang ein bisschen ein Chaos.
Außerdem kann der plötzliche große Fehler von einer Sekunde zu
Überschwingen führen (je nach Algorithmus).
2) Man stellt exakt um Mitternacht UTC die Zeit auf 23:59:59 zurück.
Diese Sekunde ist dann doppelt. Das war klassischerweise das, was
NTP-Implementationen gemacht haben (NTP setzt rechtzeitig vorher ein
NTP-Flag, damit die Clients diesen Sprung exakt timen können).
Vorteil: Die Zeit ist bis 23:59:59 korrekt und ab 00:00:00 wieder.
Man hat nur 2 Sekunden Chaos, aber da geballt, da viele Programme
mit einem Rückwärtssprung in der Zeit nicht zurechtkommen.
Beispielsweise „make“, das sich darauf verlässt, dass die Uhr nie
rückwärts geht, ist so ein Programm.
Post by Peter J. Holzer3) Man "verschmiert" die Schaltsekunde. 12 Stunden vorher macht man die
Uhr um 1/86400 langsamer, 12 Stunden nachher schaltet man wieder auf
normale Geschwindigkeit. Damit hat vor 10 Jahren oder so Google
angefangen, und seitdem haben das etliche übernommen. Vorteil: Es
gibt keinen Zeitsprung, und weil alle Computer (die dieses Verfahren
einsetzen) synchron falsch gehen, gibt es auch keine Diskrepanzen
zwischen den Computern. Nachteil: Alle Computer gehen 24 h rund um
die Schaltsekunde um bis zu einer halben Sekunde falsch (zuerst
nach, dann vor) und außerdem zu langsam.
Mit glibc gibt es noch eine Möglichkeit, die nicht zu POSIX
kompatibel ist:
Man lässt die Maschine Schaltsekunden mitzählen, das heißt, im
Fall einer Schaltsekunde hält man den Sekundenzähler, der die
Sekunden seit 1970-01-01T00:00:00Z zählt, weder für eine Sekunde
an, noch stellt man ihn eine Sekunde zurück, noch lässt man ihn
in der Umgebung der Schaltsekunde langsamer laufen, sodass also
jede Schaltsekunde seit 1970-01-01T00:00:00Z den Sekundenzähler
eine Sekunde weiterzählen lässt.
Dadurch, dass der Sekundenzähler stur durchläuft, hält er mit dem
Sekundenzähler der internationalen Atomzeit (TAI,
<https://de.wikipedia.org/wiki/Internationale_Atomzeit#top>)
Schritt, d. h. er bleibt über die Schaltsekunden hinweg in
konstantem Abstand zur TAI. Weil inzwischen 37 Schaltsekunden
aufgelaufen sind, der Zähler also seit 1970-01-01T00:00:00Z 37
Mal angehalten worden war, stellt man ihn (also die Systemuhr)
derzeit einmalig um 37 Sekunden voran, damit er auf die TAI kommt
(und zukünftig bei ihr bleibt).
Dann teilt man glibc (und damit auch dem Programm „date“) mittels
der Umgebungsvariablen „TZDIR“ und „TZ“ und/oder der Datei
„localtime“ mit, die Variante der Zeitzonendatenbank, die
Schaltsekunden enthält, zu verwenden. (Würde man das nicht tun,
bekäme man die TAI anstelle der UTC angezeigt.)
Beispielsweise sind mit dem Shell‐Kommando (mit GNU‐date)
(
for schaltsekunde in \
'1972-06-30 23:59:60' \
'1972-12-31 23:59:60'
do
echo
for umgebung in 'now -1 seconds' '' 'now +1 seconds'
do
printf 'TZ=":Etc/UTC" %s %s\n' "$schaltsekunde" "$umgebung"
done |
TZDIR=/usr/share/zoneinfo/right/ TZ=:Etc/UTC \
date -f - -- \
'+%Y-%m-%dT%TZ = %s Sekunden seit 1970-01-01T00:00:00Z'
done
)
die erste und die zweite Schaltsekunde mit jeweils der Sekunde
davor und der danach zu sehen:
1972-06-30T23:59:59Z = 78796799 Sekunden seit 1970-01-01T00:00:00Z
1972-06-30T23:59:60Z = 78796800 Sekunden seit 1970-01-01T00:00:00Z
1972-07-01T00:00:00Z = 78796801 Sekunden seit 1970-01-01T00:00:00Z
1972-12-31T23:59:59Z = 94694400 Sekunden seit 1970-01-01T00:00:00Z
1972-12-31T23:59:60Z = 94694401 Sekunden seit 1970-01-01T00:00:00Z
1973-01-01T00:00:00Z = 94694402 Sekunden seit 1970-01-01T00:00:00Z
Das hat den Vorteil, dass die Uhr bei Schaltsekunden nicht
nachgeführt werden muss, sondern unbehelligt weiterlaufen kann:
Sie macht keine Pausen und keine Sprünge, jede Sekunde ist gleich
lang, und auch die Schaltsekunden, die ja tatsächlich auftreten
(wie man mit jeder Stoppuhr im Beobachten einer DCF77‐Funkuhr
nachprüfen kann), haben ihre Entsprechung im Sekundenzähler.
Post by Peter J. HolzerAuf POSIX-kompatiblen Betriebssystemen ist 23:59:60 nicht
abbildbar. 2016-12-31T23:59:59Z war 1483228799 und
2017-01-01T00:00:00Z war 1483228800. Dazwischen ist kein Platz
für eine weitere Sekunde.
Mit der geschilderten Abweichung von POSIX ist dann auch
1972-06-30T23:59:60Z eine gültige Zeitangabe, denn sie hat ihren
Platz im Sekundenzähler.