Drucken Sie die aktuelle Uhrzeit… unter Berücksichtigung von Schaltsekunden

9

(Anmerkung: Obwohl im Zusammenhang, ist diese Herausforderung nicht ein Duplikat dieser einen , weil es Sekunden Sprung Bestimmung erfordert automatisch statt hartzucodieren ihrer Zeit, und ist kein Duplikat dieser einen , weil die meisten Schwierigkeiten kommt , die Zeit ohne Sprung zweite Schrägstellung Bestimmung Dies ist etwas, was die meisten APIs normalerweise nicht standardmäßig tun. Daher sieht eine Lösung wahrscheinlich anders aus als eine Lösung für eine dieser Herausforderungen.)

Wir kommen bis Ende 2016, aber es wird etwas länger dauern, als die meisten Leute erwarten. Hier ist also eine Herausforderung, um unsere zusätzliche Sekunde in diesem Jahr zu feiern.

Geben Sie die aktuelle Zeit in UTC als Stunden, Minuten, Sekunden aus. (Zu den legitimen Ausgabeformaten für den Mittag gehören beispielsweise 12:00:00und [12,0,0]; die Formatierung ist hier nicht besonders wichtig.)

Allerdings gibt es einen Haken: Ihr Programm umgehen müssen Schaltsekunden angemessen, sowohl Vergangenheit und Zukunft. Dies bedeutet, dass Ihr Programm eine Liste von Schaltsekunden von einer online oder automatisch aktualisierten / aktualisierbaren Quelle erhalten muss. Sie können eine Verbindung zum Internet herstellen, um dies zu erhalten, wenn Sie dies wünschen. Sie dürfen jedoch nur eine Verbindung zu einer URL herstellen, die vor dieser Herausforderung liegt (dh keine Teile Ihres Programms von einer anderen Stelle herunterladen), und Sie dürfen die Verbindung nicht verwenden, um die aktuelle Uhrzeit zu bestimmen (insbesondere: Ihr Programm muss funktionieren, auch wenn versucht wird, darauf zuzugreifen Das Internet gibt eine Seite zurück, die bis zu 24 Stunden alt ist.

Die Standard-APIs der meisten Betriebssysteme für die aktuelle Zeit verschieben die Zeit um Schaltsekunden, um sie vor Programmen zu verbergen, die sonst möglicherweise verwirrt wären. Daher besteht die Hauptschwierigkeit dieser Herausforderung darin, eine Methode oder eine API zu finden, um dies rückgängig zu machen, und die wahre unveränderte aktuelle Zeit in UTC zu ermitteln.

Theoretisch sollte Ihr Programm absolut genau sein, wenn es auf einem unendlich schnellen Computer ausgeführt wird, und es darf nicht absichtlich länger als null Zeit dauern. (In der Praxis wird Ihr Programm natürlich auf einem fehlerhaften Computer ausgeführt und daher wahrscheinlich nicht sofort ausgeführt. Sie müssen sich keine Sorgen machen, dass die Ergebnisse dadurch ungültig werden, müssen sich jedoch nicht auf die Richtigkeit Ihres Programms verlassen. )

Ihr Programm muss unabhängig von der Zeitzone funktionieren, auf die die Systemuhr eingestellt ist. (Möglicherweise werden jedoch vom Betriebssystem oder der Umgebung Informationen darüber angefordert, welche Zeitzone verwendet wird, und es kann davon ausgegangen werden, dass die Antwort korrekt ist.)

Als gewinnt das kürzeste Programm. Viel Glück!

Gemeinschaft
quelle

Antworten:

2

PowerShell , 161 Byte

(('{0:H:m:s}','23:59:60')[(($d=[datetime]::UtcNow).Ticks-6114960*98e9)/1e8-in((irm ietf.org/timezones/data/leap-seconds.list)-split'[^@]	|
'-match'^\d{9}')])-f$d

Probieren Sie es online aus! (funktioniert hier nicht, es scheint, dass TIO es nicht erkennt irmund iwrvielleicht ist es ein Sicherheitsmerkmal?)

Logiktest (fest codiertes Datum):

(('{0:H:m:s}','23:59:60')[(($d=[datetime]'1/1/2017 00:00:00').Ticks-6114960*98e9)/1e8-in((irm ietf.org/timezones/data/leap-seconds.list)-split'[^@]	|
'-match'^\d{9}')])-f$d

Anmerkungen

Die Regex-Zeichenfolge enthält einen Literal- TABund einen Literal-Zeilenumbruch ( 0xA), sodass ich ihnen nicht entkommen musste (jeweils 1 Byte gespeichert).

Erläuterung

Die in der ietf-Datei angegebenen Zeiten (der Schaltsekunden) sind in Sekunden seit der NTP-Epoche angegeben 1/1/1900 00:00:00. Unter Windows ist ein "Tick" einfach eine Zehnmillionstelsekunde (10.000.000 Ticks / Sek.).

Wenn Sie eine Ganzzahl zu einer hinzufügen [datetime], zählt sie den Ganzzahlwert als Ticks. Daher verwende ich den fest codierten Tick-Wert der NTP-Epoche und subtrahiere ihn dann vom Tick-Wert der aktuellen UTC-Zeit (deren ursprünglicher Wert gleichzeitig zugewiesen wird zu $d).

Um diesen fest codierten Tick-Wert zu verkleinern, habe ich einige Nullen (9 davon) weggenommen und durch 98 geteilt und dann mit 98e9(98 * 10 9 ) multipliziert .

Das Ergebnis dieser Subtraktion ist der Wert in Ticks seit der NTP-Epoche. Das wird geteilt durch 1e8(nicht 1e9aus Gründen, die gleich klar sein werden), um den Wert in Sekunden (irgendwie) seit der NTP-Epoche zu erhalten. Es wird tatsächlich um den Faktor 10 kleiner sein.

Nachdem ich das Dokument aus der IETF abgerufen hatte, anstatt es zuerst in Zeilen aufzuteilen und dann die Zeilen mit den Zeitstempeln zu verarbeiten, entschied ich mich, sowohl Zeilenumbrüche als auch TABZeichen aufzuteilen , da dies nach dem Zeitstempel erfolgt. Aufgrund einer einzelnen fehlerhaften Zeile in der Datei würde dies allein einen zusätzlichen Zeitstempel enthalten, den wir nicht möchten. Die Linie sieht so aus:

#@	3707596800

Also habe ich den regulären Ausdruck so geändert, dass er geteilt wird [^@]\t(jedes Zeichen, dem kein a @folgt TAB), wodurch diese Zeile ausgeschlossen wird, aber auch der letzte 0in jedem der Zeitstempel verbraucht wird .

Deshalb teile ich durch 1e8und nicht 1e9, um die Vermissten zu erklären 0.

Der aktuelle Zeitstempel wird überprüft, um festzustellen, ob er in der Liste der kastrierten Schaltsekunden-Zeitstempel vorhanden ist. Dieser gesamte von mir beschriebene Prozess befindet sich im Array-Accessor [], sodass der resultierende [bool]Wert zu a 0( $false) oder 1( $true) zusammengeführt wird. Das Array, in das wir indizieren, enthält zwei Elemente: eine Formatzeichenfolge zur Anzeige der Uhrzeit und eine fest codierte 23:59:60. Die Richtigkeit des oben genannten Vergleichs bestimmt, welcher ausgewählt wird, und dieser wird dem Formatoperator -fmit dem zuvor zugewiesenen aktuellen Datum $dals Parameter zugeführt .

Briantist
quelle
Was druckt diese Sekunde nach einer Schaltsekunde? Ich kann der Logik für Schaltsekunden folgen, bin mir aber nicht sicher, ob ich der Logik für beide Seiten folgen kann. (Zeigt Windows natürlich sowohl eine
@ ais523 zeigt die Sekunde nach der Schaltsekunde als die Systemzeit an. Windows kennt keine Schaltsekunden, daher ist die Uhr 1 Sekunde schnell, bis sie durch eine Synchronisierung oder manuelle Einstellung korrigiert wird. Angesichts der Anforderungen kann ich mich nicht wirklich darauf einstellen, da es nicht möglich ist, festzustellen, ob die Systemzeit korrekt ist oder nicht, ohne eine externe Zeitquelle zu verwenden, die gesperrt ist. Das Beste, was ich tun kann, ist, Code hinzuzufügen, der die NTP-Synchronisierung erzwingt, nachdem die Zeit gedruckt wurde. Dies kann natürlich fehlschlagen (Netzwerkfehler, keine Zeitquelle festgelegt usw.), wenn dies überhaupt zulässig ist.
Briantist