Imprimer l'heure actuelle… en tenant compte des secondes intercalaires

9

(Remarque: bien que lié, ce défi n'est pas un doublon de celui-ci car il nécessite de déterminer automatiquement les secondes intercalaires plutôt que de coder en dur leur temps, et n'est pas un doublon de celui-ci car la plupart de la difficulté vient de la détermination du temps sans biais de seconde intercalaire , ce que la plupart des API ne font pas par défaut. En tant que tel, une solution sera probablement différente d'une solution pour l'un ou l'autre de ces défis.)

Nous arrivons à la fin de 2016, mais cela va prendre un peu plus de temps que ce que la plupart des gens attendent. Voici donc un défi pour célébrer notre deuxième seconde cette année.

Affiche l'heure actuelle en UTC, en heures, minutes, secondes. (Par exemple, les formats de sortie légitimes pour midi incluraient 12:00:00et [12,0,0]; le formatage n'est pas massivement important ici.)

Cependant, il y a une torsion: votre programme doit gérer les secondes intercalaires de manière appropriée, passées et futures. Cela signifie que votre programme devra obtenir une liste de secondes intercalaires auprès d'une source en ligne ou automatiquement mise à jour / pouvant être mise à jour. Vous pouvez vous connecter à Internet pour l'obtenir si vous le souhaitez. Cependant, vous ne pouvez vous connecter qu'à une URL antérieure à ce défi (c.-à-d. Pas de téléchargement de parties de votre programme ailleurs), et vous ne pouvez pas utiliser la connexion pour déterminer l'heure actuelle (en particulier: votre programme doit fonctionner même si une tentative d'accès Internet renvoie une page qui est périmée jusqu'à 24 heures).

La plupart des API par défaut des systèmes d'exploitation pour l'heure actuelle inclineront le temps autour des secondes intercalaires afin de les cacher des programmes qui pourraient autrement être confondus. En tant que tel, la principale difficulté de ce défi est de trouver une méthode ou une API pour annuler cela et déterminer l'heure réelle non modifiée en UTC.

En théorie, votre programme doit être parfaitement précis s'il s'exécute sur un ordinateur infiniment rapide et ne doit pas prendre intentionnellement plus de temps pour s'exécuter. (Bien sûr, dans la pratique, votre programme s'exécutera sur un ordinateur imparfait et ne s'exécutera donc probablement pas instantanément. Vous n'avez pas à vous soucier de l'invalidation des résultats, mais ne devez pas en dépendre pour l'exactitude de votre programme. )

Votre programme doit fonctionner quel que soit le fuseau horaire sur lequel l'horloge système est réglée. (Cependant, il peut demander au système d'exploitation ou à l'environnement des informations sur le fuseau horaire utilisé et peut supposer que la réponse est exacte.)

En tant que , le programme le plus court gagne. Bonne chance!

Communauté
la source

Réponses:

2

PowerShell , 161 octets

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

Essayez-le en ligne! (ne fonctionne pas ici, il semble que TIO ne reconnaisse pas irmet iwr, peut-être que c'est une fonction de sécurité?)

Test logique (date codée en dur):

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

Remarques

Il y a un littéral TABet un saut de ligne littéral ( 0xA) dans la chaîne d'expression régulière , de sorte que je n'ai pas eu à les échapper (enregistré 1 octet chacun).

Explication

Les temps donnés (des secondes intercalaires) dans le fichier ietf sont en secondes depuis l'époque NTP qui est 1/1/1900 00:00:00. Sous Windows, un "tick" est simplement un dix millionième de seconde (10 000 000 ticks / sec).

Si vous ajoutez un entier à un, [datetime]il compte la valeur entière comme des ticks, donc j'utilise la valeur de tick codée en dur de l'époque NTP, puis je la soustrais de la valeur de tick de l'heure UTC actuelle (dont la valeur d'origine est simultanément affectée à $d).

Pour réduire cette valeur de tick codée en dur, j'ai enlevé quelques zéros (9 d'entre eux) et divisé par 98, puis multiplié par 98e9(98 * 10 9 ).

Le résultat de cette soustraction est la valeur en ticks depuis l'époque NTP. Cela est divisé par 1e8(non 1e9, pour des raisons qui seront claires dans un instant) pour obtenir la valeur en secondes (en quelque sorte) depuis l'époque NTP. En fait, il sera plus petit d'un facteur 10.

Récupérer le document de l'IETF, plutôt que de le diviser en lignes d'abord, puis de traiter les lignes avec les horodatages, j'ai décidé de diviser à la fois les sauts de ligne et les TABcaractères, car c'est ce qui vient après l'horodatage. En raison d'une seule ligne errante dans le fichier, cela seul inclurait un horodatage supplémentaire que nous ne voulons pas. La ligne ressemble à ceci:

#@	3707596800

J'ai donc changé l'expression régulière pour la scinder [^@]\t(tout caractère non @suivi d'un TAB) qui fonctionne pour exclure cette ligne, mais finit également par consommer le dernier 0dans chacun des horodatages.

C'est pourquoi je divise par 1e8et non 1e9, pour tenir compte des disparus 0.

L'horodatage actuel est vérifié pour voir s'il existe à l'intérieur de la liste des horodatages en seconde intercalaire castrée. L'ensemble de ce processus que j'ai décrit est à l'intérieur de l'accesseur de tableau [], donc la [bool]valeur résultante est fusionnée en a 0( $false) ou 1( $true). Le tableau dans lequel nous indexons contient deux éléments: une chaîne de format pour afficher l'heure et un codé en dur 23:59:60. La véracité de la comparaison susmentionnée détermine celle qui sera choisie, et celle qui est introduite dans l'opérateur de format -favec la date actuelle précédemment attribuée $dcomme paramètre.

briantiste
la source
Qu'est-ce que cela imprime la seconde après une seconde intercalaire? Je peux suivre la logique pendant des secondes intercalaires, mais je ne suis pas sûr de pouvoir suivre la logique des fois de chaque côté. (Windows affiche-t-il naturellement à la fois une seconde
@ ais523, il affichera la seconde après la seconde intercalaire comme l'heure système. Windows ne connaît pas les secondes intercalaires, donc l'horloge sera rapide d'une seconde jusqu'à ce qu'elle soit corrigée par une synchronisation ou un réglage manuel. Étant donné les exigences, je ne peux pas vraiment m'adapter à cela, car il n'est pas possible de déterminer si l'heure du système est correcte ou non sans utiliser une source de temps externe, ce qui est interdit. Le mieux que je puisse faire est d'ajouter du code à cela qui force la synchronisation NTP après avoir imprimé l'heure, ce qui pourrait bien sûr échouer (erreur réseau, aucune source de temps définie, etc.), si cela est même autorisé.
briantist