Stampa l'ora corrente ... tenendo conto dei secondi intercalari


9

(Nota: sebbene correlata, questa sfida non è un duplicato di questo perché richiede la determinazione automatica dei secondi bisestili piuttosto che la codifica dei loro tempi, e non è un duplicato di questo perché la maggior parte delle difficoltà deriva dal determinare il tempo senza saltare i secondi obliqui , cosa che la maggior parte delle volte le API non eseguono per impostazione predefinita. Pertanto, è probabile che una soluzione appaia diversa da una soluzione a una di queste sfide.)

Arriveremo alla fine del 2016, ma ci vorrà un po 'più di tempo di quanto molti si aspettino. Quindi ecco una sfida che celebra il nostro secondo in più quest'anno.

Emette l'ora corrente in UTC, come ore, minuti, secondi. (Ad esempio, i formati di output legittimi per mezzogiorno includeranno 12:00:00e [12,0,0]; la formattazione non è estremamente importante qui.)

Tuttavia, c'è una svolta: il tuo programma deve gestire i secondi bisestili in modo appropriato, sia passato che futuro. Ciò significa che il tuo programma dovrà ottenere un elenco di secondi bisestili da una fonte online o automaticamente aggiornata / aggiornabile. Se lo desideri, puoi connetterti a Internet per ottenerlo. Tuttavia, è possibile connettersi solo a un URL che precede questa sfida (ovvero non scaricare parti del programma da altrove) e non è possibile utilizzare la connessione per determinare l'ora corrente (in particolare: il programma deve funzionare anche se qualsiasi tentativo di accedere Internet restituisce una pagina non aggiornata fino a 24 ore).

La maggior parte delle API predefinite dei sistemi operativi per l'ora corrente distorcerà il tempo intorno ai secondi bisestili per nasconderle da programmi che potrebbero altrimenti essere confusi. Pertanto, la principale difficoltà di questa sfida è trovare un metodo o un'API per annullarlo e calcolare l'ora reale non modificata in UTC.

In teoria, il tuo programma dovrebbe essere perfettamente accurato se eseguito su un computer infinitamente veloce e non deve impiegare intenzionalmente più di zero tempo per essere eseguito. (Naturalmente, in pratica, il tuo programma verrà eseguito su un computer imperfetto, quindi probabilmente non verrà eseguito istantaneamente. Non devi preoccuparti che questo invalidi i risultati, ma non devi dipendere da esso per la correttezza del tuo programma. )

Il programma deve funzionare indipendentemente dal fuso orario su cui è impostato l'orologio di sistema. (Tuttavia, può richiedere informazioni al sistema operativo o all'ambiente su quale fuso orario viene utilizzato e può presumere che la risposta sia accurata.)

Come , vince il programma più breve. In bocca al lupo!


Risposte:


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

Provalo online! (non funziona qui, sembra che TIO non riconosca irme iwr, forse, è una funzione di sicurezza?)

Test logico (data hardcoded):

(('{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

Appunti

C'è una letterale TABe letterale interruzione di riga ( 0xA) nella stringa regex, quindi non ho dovuto scappare da loro (salvato 1 byte ciascuno).

Spiegazione

I tempi indicati (dei secondi bisestili) nel file ietf sono in secondi dall'epoca NTP che è 1/1/1900 00:00:00. Su Windows, un "tick" è semplicemente un decimilionesimo di secondo (10.000.000 di tick / sec).

Se aggiungi un numero intero ad un [datetime]conteggio del valore intero come tick, quindi sto usando il valore di tick hardcoded dell'epoca NTP, quindi sottraendolo dal valore di tick dell'ora UTC corrente (il cui valore originale viene assegnato contemporaneamente a $d).

Per ridurre quel valore di tick codificato, ho rimosso alcuni zeri (9 di essi) e diviso per 98, quindi moltiplicato per 98e9(98 * 10 9 ).

Il risultato di tale sottrazione è il valore in tick dall'epoca NTP. Questo viene diviso per 1e8(non 1e9, per ragioni che saranno chiare in un attimo) per ottenere il valore in secondi (più o meno) dall'epoca NTP. In realtà sarà più piccolo di un fattore 10.

Recuperando il documento dall'IETF, anziché dividerlo prima in linee, quindi elaborare le linee con i timestamp, ho deciso di dividere su entrambe le interruzioni di riga e sui TABcaratteri, poiché è quello che viene dopo il timestamp. A causa di una singola riga errante nel file, solo questo includerebbe un timestamp aggiuntivo che non vogliamo. La linea si presenta così:

#@	3707596800

Quindi ho cambiato la regex su cui dividere [^@]\t(qualsiasi personaggio che non è @seguito da a TAB) che funziona per escludere quella linea, ma finisce anche per consumare l'ultimo 0in ciascuno dei timestamp.

Ecco perché divido per 1e8e non 1e9, per tenere conto dei dispersi 0.

Il timestamp corrente viene controllato per vedere che esiste all'interno dell'elenco dei timestamp secondari con salto saltato. L'intero processo che ho descritto è all'interno dell'accessor dell'array [], quindi il [bool]valore risultante viene unito a un 0( $false) o 1( $true). L'array in cui ci stiamo indicando contiene due elementi: una stringa di formato per la visualizzazione dell'ora e una codificata 23:59:60. La veridicità del summenzionato confronto determina quale verrà scelto e che viene inserito nell'operatore di formato -fcon la data corrente precedentemente assegnata $dcome parametro.


Cosa stampa questo secondo dopo un secondo bisestile? Posso seguire la logica per i secondi bisestili, ma non sono sicuro di poter seguire la logica per volte su entrambi i lati. (Windows mostra naturalmente sia un secondo bisestile che il secondo successivo come 00:00:00?)

@ ais523 visualizzerà il secondo dopo il secondo intercalare come qualunque sia l'ora del sistema. Windows non è a conoscenza dei secondi intercalari, quindi l'orologio sarà veloce di 1 secondo fino a quando non verrà corretto da un'impostazione di sincronizzazione o manuale. Dati i requisiti che non posso davvero adeguare per questo, dal momento che non è possibile determinare se l'ora di sistema è corretta o meno senza utilizzare una fonte di tempo esterna, che è vietata. Il meglio che potrei fare è aggiungere codice a questo che impone la sincronizzazione NTP dopo aver stampato l'ora, il che ovviamente potrebbe fallire (errore di rete, nessuna impostazione dell'origine temporale, ecc.), Se ciò è permesso.
Briantist
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.