Вывести текущее время ... с учетом дополнительных секунд


9

(Примечание: хотя связаны, эта проблема не является дубликатом этого одного , потому что он требует определения високосных секунд автоматически , а не жестко прописывать их раз, и не является дубликатом этого одного , потому что большая часть трудностей происходит от определения времени без секундной перекоса что-то, что большинство API времени не делает по умолчанию. Таким образом, решение, скорее всего, будет отличаться от решения любой из этих проблем.)

Мы приближаемся к концу 2016 года, но это займет немного больше времени, чем ожидают большинство людей. Итак, вот задача отпраздновать нашу дополнительную секунду в этом году.

Выведите текущее время в формате UTC в виде часов, минут, секунд. (Например, допустимые форматы вывода для полудня включают 12:00:00и [12,0,0]; форматирование здесь не имеет большого значения.)

Однако есть и поворот: ваша программа должна правильно обрабатывать дополнительные секунды , как прошлые, так и будущие. Это означает, что ваша программа должна будет получить список дополнительных секунд из какого-либо онлайн или автоматически обновляемого / обновляемого источника. Вы можете подключиться к Интернету, чтобы получить это, если хотите. Однако вы можете подключиться только к URL-адресу, который предшествует этой проблеме (т. Е. Не загружать части вашей программы из другого места), и вы не можете использовать подключение для определения текущего времени (в частности: ваша программа должна функционировать, даже если любая попытка доступа Интернет возвращает страницу, которая устарела до 24 часов).

API-интерфейсы большинства операционных систем по умолчанию для текущего времени будут искажены вокруг високосных секунд, чтобы скрыть их от программ, которые в противном случае могли бы быть перепутаны. Таким образом, основная трудность этой задачи состоит в том, чтобы найти метод или API, чтобы отменить это, и определить истинное неизмененное текущее время в UTC.

Теоретически, ваша программа должна быть совершенно точной, если она запускается на бесконечно быстром компьютере, и не должна намеренно запускаться более чем на ноль времени. (Конечно, на практике ваша программа будет работать на несовершенном компьютере, и поэтому, вероятно, не будет работать мгновенно. Вам не нужно беспокоиться об этом как обесценивающем результаты, но вы не должны зависеть от него для правильности вашей программы. )

Ваша программа должна работать независимо от того, на какой часовой пояс установлены системные часы. (Однако он может запросить информацию из операционной системы или среды о том, какой часовой пояс используется, и может предположить, что ответ точный.)

Как , самая короткая программа выигрывает. Удачи!


Ответы:


2

PowerShell , 161 байт

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

Попробуйте онлайн! (здесь не работает, кажется, что TIO не распознает irmи iwr, может быть, это функция безопасности?)

Логический тест (жестко закодированная дата):

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

Ноты

В строке регулярного выражения есть литерал TABи буквальный перенос строки ( 0xA), так что мне не нужно было экранировать их (сохранял 1 байт каждый).

объяснение

Заданное время (високосных секунд) в файле ietf указывается в секундах с начала эпохи NTP 1/1/1900 00:00:00. В Windows «тик» - это просто одна десятая миллионная доли секунды (10 000 000 тиков в секунду).

Если вы добавляете целое число к a, то [datetime]оно подсчитывает целочисленное значение как тики, поэтому я использую жестко закодированное значение тика эпохи NTP, а затем вычитая его из значения тика текущего времени UTC (первоначальное значение которого назначается одновременно к $d).

Чтобы уменьшить это жестко закодированное значение тика, я убрал несколько нулей (9 из них) и разделил на 98, затем умножил на 98e9(98 * 10 9 ).

Результатом этого вычитания является значение в тиках с эпохи NTP. Это делится на 1e8(а не 1e9по причинам, которые будут понятны в данный момент), чтобы получить значение в секундах (вроде) с момента появления NTP. Фактически он будет меньше в 10 раз.

Получив документ из IETF, вместо того, чтобы сначала разбивать его на строки, а затем обрабатывать строки с временными метками, я решил разделить их как на разрывы строк, так и на TABсимволы, так как это то, что следует за временной меткой. Из-за единственной ошибочной строки в файле, она одна будет включать дополнительную временную метку, которую мы не хотим. Линия выглядит так:

#@	3707596800

Поэтому я изменил регулярное выражение для разделения [^@]\t(на любой символ, за которым не @следует a TAB), которое работает для исключения этой строки, но в конечном итоге потребляет последнее 0в каждой из временных меток.

Вот почему я делю на, 1e8а не 1e9, чтобы объяснить пропавшие 0.

Текущая временная метка проверяется, чтобы увидеть, что она существует в списке стерилизованных временных меток високосных секунд. Весь этот процесс, который я описал, находится внутри метода доступа к массиву [], поэтому результирующее [bool]значение объединяется с 0( $false) или 1( $true). Массив, в который мы индексируем, содержит два элемента: строку формата для отображения времени и жестко заданный код 23:59:60. Достоверность вышеупомянутого сравнения определяет, какой из них будет выбран, и который передается в оператор форматирования -fс ранее назначенной текущей датой в $dкачестве параметра.


Что это печатает секунду после високосной секунды? Я могу следовать логике в течение високосных секунд, но не уверен, что могу следовать логике в течение некоторого времени с обеих сторон. (Естественно ли Windows отображает и високосную секунду, и следующую секунду как 00:00:00?)

@ ais523 будет отображать секунду после високосной секунды как системное время. Windows не знает о високосных секундах, поэтому часы будут работать на 1 секунду быстрее, пока не будут скорректированы с помощью синхронизации или ручной настройки. Учитывая требования, которые я не могу откорректировать для этого, так как невозможно определить, является ли системное время правильным или нет, без использования внешнего источника времени, который запрещен. Самое лучшее, что я мог сделать, это добавить к этому код, который заставит синхронизацию NTP после того, как он напечатает время, что, конечно, может дать сбой (ошибка сети, отсутствие источника времени и т. Д.), Если это даже разрешено.
бриантист
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.