Zum Schaltsekundenereignis am 30. Juni 2012 habe ich aus Interesse einige Messungen mit einem in Java selbstprogrammierten SNTP-Client vorgenommen. Andere marktübliche Implementierungen stammen von Adam Buckley, Apache Commons oder von Google-Android. Die grundlegenden Programmiermuster solcher Implementierungen sind praktisch gleich – einfach aufgrund der Anforderungen des SNTP-Protokolls. Allerdings habe ich in meiner Lösung noch einige Debugging-Ausgaben und Logging-Fähigkeiten eingebaut. Auch habe ich zum Vergleich den üblichen Ausdruck System.currentTimeMillis() nur einmalig zur Initialisierung verwendet und bin dann immer vom Ausdruck System.nanoTime() ausgegangen, da hier aus dem PC die maximal verfügbare zeitliche Genauigkeit herausgeholt werden kann.Solche Zeitmessungen werten nicht nur die vom NTP-Server gemeldeten NTP-Zeitstempel (Festkommazahlen als Anzahl der Sekunden seit dem 1. Januar 1900) aus, sondern zwecks Schätzung der Laufzeitdifferenz im Netz auch die lokale Computer-Uhr. Entscheidende Messgröße ist die so erhaltene Differenz zwischen der lokalen Computer-Uhr und der über das SNTP-Protokoll ermittelten Netzzeit. Die Standardabweichung dieses Offsets liefert dann ein Maß zur Schätzung des mittleren Fehlers (hier des Mittelwerts) und ist letztlich das statistisch relevante Ergebnis dieses Artikels.
Die Hardware-Daten sahen bei mir wie folgt aus:
Lokaler PC mit Windows 7 => Intel(R) Core i7 CPU 2.93 GHz
NTP-Server => Physikalisch-Technische Bundesanstalt in Braunschweig (PTB), Stratum 1, NTP-Adresse “ptbtime1.ptb.de”
Internet-Connection => DSL 16000
Einige für die angegebene Hardware-Konstellation typische Messdaten mit Mikrosekundenanzeige:
Connecting NTP-Server, waiting for reply…
NTP-Server connected: de.menodata.time4j.utc.net.SntpMessage[version=4, mode=server, leap-indicator=1, stratum=1, poll-interval=0, precision=-22, root-delay=0.0, root-dispersion=4.425048828125E-4, reference-identifier=PTB, reference-timestamp=2012-06-30T23:59:42,064662000Z, originate-timestamp=2012-06-30T23:59:50,809102000Z, receive-timestamp=2012-06-30T23:59:57,875550000Z, transmit-timestamp=2012-06-30T23:59:57,875559000Z]
NTP-Server signals positive leap second.
Last-Connection-Time=2012-06-30T23:59:57,898053000Z
Offset=7044423082
*************************************************
Connecting NTP-Server, waiting for reply…
NTP-Server connected: de.menodata.time4j.utc.net.SntpMessage[version=4, mode=server, leap-indicator=1, stratum=1, poll-interval=0, precision=-22, root-delay=0.0, root-dispersion=4.57763671875E-4, reference-identifier=PTB, reference-timestamp=2012-06-30T23:59:42,064662000Z, originate-timestamp=2012-06-30T23:59:51,154119000Z, receive-timestamp=2012-06-30T23:59:58,240131000Z, transmit-timestamp=2012-06-30T23:59:58,240138000Z]
NTP-Server signals positive leap second.
Last-Connection-Time=2012-06-30T23:59:58,271604000Z
Offset=7054978015
*************************************************
Connecting NTP-Server, waiting for reply…
NTP-Server connected: de.menodata.time4j.utc.net.SntpMessage[version=4, mode=server, leap-indicator=1, stratum=1, poll-interval=0, precision=-22, root-delay=0.0, root-dispersion=4.57763671875E-4, reference-identifier=PTB, reference-timestamp=2012-06-30T23:59:42,064662000Z, originate-timestamp=2012-06-30T23:59:51,517077000Z, receive-timestamp=2012-06-30T23:59:58,568375000Z, transmit-timestamp=2012-06-30T23:59:58,568382000Z]
NTP-Server signals positive leap second.
Last-Connection-Time=2012-06-30T23:59:58,583115000Z
Offset=7037023577
*************************************************
Connecting NTP-Server, waiting for reply…
NTP-Server connected: de.menodata.time4j.utc.net.SntpMessage[version=4, mode=server, leap-indicator=1, stratum=1, poll-interval=0, precision=-22, root-delay=0.0, root-dispersion=4.57763671875E-4, reference-identifier=PTB, reference-timestamp=2012-06-30T23:59:42,064662000Z, originate-timestamp=2012-06-30T23:59:51,847118000Z, receive-timestamp=2012-06-30T23:59:58,893526000Z, transmit-timestamp=2012-06-30T23:59:58,893532000Z]
NTP-Server signals positive leap second.
Last-Connection-Time=2012-06-30T23:59:58,904998000Z
Offset=7035401682
*************************************************
Connecting NTP-Server, waiting for reply…
NTP-Server connected: de.menodata.time4j.utc.net.SntpMessage[version=4, mode=server, leap-indicator=1, stratum=1, poll-interval=0, precision=-22, root-delay=0.0, root-dispersion=2.288818359375E-4, reference-identifier=PTB, reference-timestamp=2012-06-30T23:59:59,065810000Z, originate-timestamp=2012-06-30T23:59:52,170168000Z, receive-timestamp=2012-06-30T23:59:59,247781000Z, transmit-timestamp=2012-06-30T23:59:59,247788000Z]
NTP-Server signals positive leap second.
Last-Connection-Time=2012-06-30T23:59:59,275411000Z
Offset=7050516613
*************************************************
Connecting NTP-Server, waiting for reply…
NTP-Server connected: de.menodata.time4j.utc.net.SntpMessage[version=4, mode=server, leap-indicator=1, stratum=1, poll-interval=0, precision=-22, root-delay=0.0, root-dispersion=2.288818359375E-4, reference-identifier=PTB, reference-timestamp=2012-06-30T23:59:59,065810000Z, originate-timestamp=2012-06-30T23:59:52,525063000Z, receive-timestamp=2012-06-30T23:59:59,566965000Z, transmit-timestamp=2012-06-30T23:59:59,566972000Z]
NTP-Server signals positive leap second.
Last-Connection-Time=2012-06-30T23:59:59,575551000Z
Offset=7033785196
*************************************************
Connecting NTP-Server, waiting for reply…
NTP-Server connected: de.menodata.time4j.utc.net.SntpMessage[version=4, mode=server, leap-indicator=1, stratum=1, poll-interval=0, precision=-22, root-delay=0.0, root-dispersion=2.288818359375E-4, reference-identifier=PTB, reference-timestamp=2012-06-30T23:59:59,065810000Z, originate-timestamp=2012-06-30T23:59:52,842035000Z, receive-timestamp=2012-06-30T23:59:59,884087000Z, transmit-timestamp=2012-06-30T23:59:59,884093000Z]
NTP-Server signals positive leap second.
Last-Connection-Time=2012-06-30T23:59:59,892778000Z
Offset=7033833181
*************************************************
Connecting NTP-Server, waiting for reply…
NTP-Server connected: de.menodata.time4j.utc.net.SntpMessage[version=4, mode=server, leap-indicator=1, stratum=1, poll-interval=0, precision=-22, root-delay=0.0, root-dispersion=2.44140625E-4, reference-identifier=PTB, reference-timestamp=2012-06-30T23:59:59,065810000Z, originate-timestamp=2012-06-30T23:59:53,159185000Z, receive-timestamp=2012-06-30T23:59:59,256841000Z, transmit-timestamp=2012-06-30T23:59:59,256847000Z]
NTP-Server signals positive leap second.
Last-Connection-Time=2012-06-30T23:59:60,294928000Z
Offset=6060019006
Besprechung der Messdaten:
Der letzte gemessene Offset lag um ca. eine volle Sekunde kleiner, weil er als Differenz zwischen lokaler (fortlaufender) Computer-Uhr und vom NTP-Server gemessener Atomuhrzeit die Tatsache reflektiert, daß der NTP-Server eine Schaltsekunde wiederholt, also zweimal den gleichen NTP-Zeitstempel liefert (im Rahmen einer Sekundenanzeige ohne Berücksichtigung der Nachkommastellen). Gleichzeitig läuft die Windows-Computer-Uhr trotz der Schaltsekunde einfach weiter. Daher wird auf den letzten zu kleinen Offset eine Sekunde aufaddiert, um dann die Fehlerrechnung anzuwenden.
Offset-Mittelwert der Stichprobe = 7,043747544 Sekunden
Standard-Abweichung der Einzelwerte = 0,010348006 Sekunden
Standard-Abweichung des Mittelwerts = 0,003658572 Sekunden
Ergebnis: Offset ~ 7,044 +/- 0,004 Sekunden
Die unter Windows-Betriebssystemen übliche Genauigkeit von ca. 10 Millisekunden konnte also auf besser als 4 Millisekunden gesteigert werden. Allerdings führt Windows gelegentlich selber automatische NTP-Synchronisationen mit meistens dem Windows-Time-Server unter “time.windows.com” aus, die zu größeren Sekundensprüngen in der lokalen PC-Zeit führen können. Bei den oben angegebenen Messdaten ist nach einem Blick in die Windows-Systemprotokolle sichergestellt, daß die Messdaten durch diese unabhängigen Synchronisationsvorgänge nicht verfälscht worden sind. Umgekehrt ist natürlich hieraus auch zu folgern, daß die NTP-Zeit wesentlich zuverlässiger als die PC-Uhr ist (der Offset im Beispiel von ca. 7 Sekunden ist erheblich bei lange nicht erfolgter Windows-Synchronisation).
Interessant ist auch, daß der PTB-Server zwar ständig einen leap-indicator (=1) sendet, aber dieser nicht geeignet ist, die aktuelle Schaltsekunde abzufragen. Vielmehr kündet er nur eine kommende UTC-Schaltsekunde an. Und dieses Flag wird auch nicht sofort mit Ende der eingefügten Schaltsekunde abgeschaltet. So wurde es auch mehr als 3 Minuten danach noch von der PTB gesendet:
Connecting NTP-Server, waiting for reply…
NTP-Server connected: de.menodata.time4j.utc.net.SntpMessage[version=4, mode=server, leap-indicator=1, stratum=1, poll-interval=0, precision=-22, root-delay=0.0, root-dispersion=3.662109375E-4, reference-identifier=PTB, reference-timestamp=2012-07-01T00:03:37,080589000Z, originate-timestamp=2012-07-01T00:03:40,327099000Z, receive-timestamp=2012-07-01T00:03:46,367308000Z, transmit-timestamp=2012-07-01T00:03:46,367315000Z]
NTP-Server signals positive leap second.
Last-Connection-Time=2012-07-01T00:03:46,376627000Z
Offset=6031366725
Erst ungefähr 8 Minuten später hat das leap-indicator-Flag den Normalwert 0. Zusammengefasst läßt sich sagen, daß das leap-indicator-Flag des NTP-Protokolls keine Möglichkeit bietet, eine bestimmte Sekunde als Schaltsekunde zu qualifizieren. Erst der Vergleich mit einer lokalen PC-Uhr in Kombination mit einem Offset-Sprung von ca. 1 Sekunde gestattet dies.