Wydrukuj aktualny czas… biorąc pod uwagę sekundy przestępne


9

(Uwaga: pomimo tego, że jest to powiązane, to wyzwanie nie jest duplikatem tego, ponieważ wymaga automatycznego określenia sekund przestępnych, a nie zakodowania ich czasów i nie jest duplikatem tego, ponieważ większość trudności wynika z określenia czasu bez drugiego skoku , coś, czego większość interfejsów API nie robi domyślnie. W związku z tym rozwiązanie może wyglądać inaczej niż rozwiązanie któregoś z tych wyzwań).

Zbliżamy się do końca 2016 roku, ale potrwa to nieco dłużej, niż większość ludzi się spodziewa. Oto wyzwanie świętowania naszej dodatkowej sekundy w tym roku.

Podaj aktualny czas w UTC, jako godziny, minuty, sekundy. (Na przykład prawidłowe formaty wyjściowe na południe powinny zawierać 12:00:00i [12,0,0]; formatowanie nie jest tutaj niezwykle ważne).

Jest jednak pewien zwrot: twój program musi odpowiednio obsługiwać sekundy przestępne , zarówno z przeszłości, jak i przyszłości. Oznacza to, że Twój program będzie musiał uzyskać listę sekund przestępnych z niektórych źródeł online lub automatycznie aktualizowanych / aktualizowanych. Jeśli chcesz, możesz połączyć się z Internetem. Możesz jednak połączyć się tylko z adresem URL, który wyprzedza to wyzwanie (tj. Nie pobierać części programu z innego miejsca) i nie możesz używać połączenia do określenia aktualnego czasu (w szczególności: Twój program musi działać, nawet jeśli jakakolwiek próba dostępu Internet zwraca stronę, która jest do 24 godzin nieaktualna).

Domyślne interfejsy API większości systemów operacyjnych na bieżący czas będą przechylać czas około sekund przestępnych, aby ukryć je przed programami, które w innym przypadku mogłyby zostać pomylone. W związku z tym główną trudnością tego wyzwania jest znalezienie metody lub interfejsu API w celu cofnięcia tego i obliczenia prawdziwego niezmodyfikowanego bieżącego czasu w UTC.

Teoretycznie twój program powinien być idealnie dokładny, jeśli działał na nieskończenie szybkim komputerze i nie mógł celowo działać dłużej niż zero czasu. (Oczywiście w praktyce Twój program będzie działał na niedoskonałym komputerze, a więc prawdopodobnie nie uruchomi się natychmiast. Nie musisz się martwić o unieważnienie wyników, ale nie możesz polegać na nim pod względem poprawności programu. )

Twój program musi działać niezależnie od strefy czasowej, na którą ustawiony jest zegar systemowy. (Może jednak zażądać od systemu operacyjnego lub środowiska informacji o używanej strefie czasowej i może założyć, że odpowiedź jest poprawna).

Jak wygrywa najkrótszy program. Powodzenia!


Odpowiedzi:


2

PowerShell , 161 bajtów

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

Wypróbuj online! (tutaj nie działa, wygląda na to, że TIO nie rozpoznaje irmi iwrmoże to funkcja bezpieczeństwa?)

Test logiczny (data zakodowania):

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

Notatki

W łańcuchu wyrażeń regularnych występuje literał TABi dosłowny podział wiersza ( 0xA), więc nie musiałem przed nimi uciekać (zapisałem 1 bajt każdy).

Wyjaśnienie

Czasy podane (w sekundach przestępnych) w pliku ietf są w sekundach od epoki NTP, która jest 1/1/1900 00:00:00. W systemie Windows „tyknięcie” to po prostu jedna dziesiąta milionowej sekundy (10 000 000 tyknięć / s).

Jeśli dodasz liczbę całkowitą do [datetime], liczona jest wartość całkowita jako tiki, więc używam zakodowanej wartości tonu z epoki NTP, a następnie odejmuję ją od wartości tiku bieżącego czasu UTC (której pierwotna wartość jest jednocześnie przypisywana do $d).

Aby zmniejszyć wartość zaznaczenia na sztywno, zabrałem kilka zer (9 z nich) i podzieliłem przez 98, a następnie pomnożyłem przez 98e9(98 * 10 9 ).

Wynikiem tego odejmowania jest wartość w tikach od epoki NTP. Dzieli się to 1e8(nie 1e9, z powodów, które za chwilę będą jasne), aby uzyskać wartość w sekundach (w pewnym sensie) od epoki NTP. W rzeczywistości będzie mniejszy 10 razy.

Odzyskując dokument z IETF, zamiast najpierw podzielić go na linie, a następnie przetworzyć linie ze znacznikami czasu, postanowiłem podzielić zarówno na podziały linii, jak i na TABznaki, ponieważ to jest po znaczniku czasu. Z powodu pojedynczej błędnej linii w pliku, sam ten zawierałby dodatkowy znacznik czasu, którego nie chcemy. Linia wygląda następująco:

#@	3707596800

Zmieniłem więc wyrażenie regularne na split [^@]\t(dowolny znak, po którym nie @następuje a TAB), co działa w celu wykluczenia tej linii, ale w końcu pochłania ostatnie 0w każdym ze znaczników czasu.

Dlatego dzielę według, 1e8a nie 1e9, aby uwzględnić brakujące 0.

Bieżący znacznik czasu jest sprawdzany, aby zobaczyć, czy istnieje on na liście znaczników czasowych drugiego wyskoku. Cały ten proces, który opisałem, znajduje się wewnątrz akcesorium tablicowego [], więc wynikowa [bool]wartość jest łączona w 0( $false) lub 1( $true). Tablica, w której indeksujemy, zawiera dwa elementy: ciąg formatu do wyświetlania czasu i zakodowany na stałe 23:59:60. Prawdziwość wspomnianego porównania określa, które zostanie wybrane, i które jest podawane do operatora formatu -fz wcześniej przypisaną bieżącą datą $djako parametrem.


Co ten drukuje sekundę po sekundie przestępnej? Mogę podążać za logiką przez kilka sekund przestępnych, ale nie jestem pewien, czy potrafię podążać za logiką razy po obu stronach. (Czy system Windows naturalnie wyświetla zarówno sekundę przestępną, jak i następną sekundę jako 00:00:00?)

@ ais523 wyświetli sekundę po sekundie przestępnej, niezależnie od czasu systemowego. System Windows nie wie o sekundach przestępnych, więc zegar będzie szybki o 1 sekundę, dopóki nie zostanie poprawiony przez synchronizację lub ustawienie ręczne. Biorąc pod uwagę wymagania, nie mogę się do tego dostosować, ponieważ nie można ustalić, czy czas systemowy jest poprawny, czy nie bez użycia zewnętrznego źródła czasu, które jest zakazane. Najlepsze, co mogłem zrobić, to dodać do tego kod, który wymusza synchronizację NTP po wydrukowaniu czasu, co oczywiście może się nie powieść (błąd sieci, brak ustawienia źródła czasu itp.), Nawet jeśli jest to dozwolone.
briantist
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.