Cetak waktu saat ini ... dengan lompatan detik ke akun

9

(Catatan: meskipun terkait, tantangan ini bukan duplikat dari yang satu ini karena membutuhkan menentukan lompatan detik secara otomatis daripada meng-hardcoding waktu mereka, dan bukan duplikat dari yang ini karena sebagian besar kesulitan berasal dari menentukan waktu tanpa melompati skewing kedua , sesuatu yang sebagian besar waktu API tidak lakukan secara default. Dengan demikian, sebuah solusi cenderung terlihat berbeda dari solusi untuk salah satu dari tantangan tersebut.)

Kami akan tiba di akhir 2016, tetapi akan memakan waktu sedikit lebih lama dari yang diperkirakan kebanyakan orang. Jadi, inilah tantangan untuk merayakan detik tambahan kami tahun ini.

Keluarkan waktu saat ini dalam UTC, seperti jam, menit, detik. (Misalnya, format output yang sah untuk tengah hari akan mencakup 12:00:00dan [12,0,0]; format tidak penting secara signifikan di sini.)

Namun, ada twist: program Anda harus menangani detik kabisat tepat, baik masa lalu dan masa depan. Ini berarti bahwa program Anda harus memperoleh daftar detik kabisat dari beberapa sumber daring atau yang diperbarui secara otomatis. Anda dapat terhubung ke Internet untuk mendapatkan ini jika Anda mau. Namun, Anda hanya dapat terhubung ke URL yang mendahului tantangan ini (mis. Tidak ada pengunduhan bagian dari program Anda dari tempat lain), dan Anda tidak boleh menggunakan koneksi untuk menentukan waktu saat ini (khususnya: program Anda harus berfungsi bahkan jika ada upaya untuk mengakses Internet mengembalikan halaman yang basi hingga 24 jam).

API default sebagian besar sistem operasi untuk waktu saat ini akan membelokkan waktu sekitar detik kabisat untuk menyembunyikannya dari program yang mungkin membingungkan. Dengan demikian, kesulitan utama dari tantangan ini adalah menemukan metode atau API untuk membatalkannya, dan menghitung waktu saat ini yang belum dimodifikasi di UTC.

Secara teori, program Anda harus benar-benar akurat jika dijalankan pada komputer yang sangat cepat, dan tidak boleh sengaja mengambil lebih dari nol waktu untuk berjalan. (Tentu saja, dalam praktiknya, program Anda akan berjalan pada komputer yang tidak sempurna, dan karenanya mungkin tidak akan berjalan secara instan. Anda tidak perlu khawatir tentang ini akan membatalkan hasil, tetapi tidak harus bergantung padanya untuk kebenaran program Anda. )

Program Anda harus berfungsi terlepas dari zona waktu mana jam sistem diatur. (Namun, dapat meminta informasi dari sistem operasi atau lingkungan tentang zona waktu apa yang digunakan, dan dapat berasumsi bahwa balasannya akurat.)

Sebagai , program terpendek menang. Semoga berhasil!

Komunitas
sumber

Jawaban:

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

Cobalah online! (tidak berfungsi di sini, sepertinya TIO tidak mengenali irmdan iwr, mungkin itu fitur keamanan?)

Tes Logika (Tanggal 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

Catatan

Ada TABlinebreak literal dan literal ( 0xA) di string regex, sehingga saya tidak perlu melarikan diri (disimpan masing-masing 1 byte).

Penjelasan

Waktu yang diberikan (dari detik kabisat) dalam file ietf adalah dalam detik sejak zaman NTP 1/1/1900 00:00:00. Di Windows, "tick" hanya sepersepuluh juta detik (10.000.000 ticks / sec).

Jika Anda menambahkan bilangan bulat ke [datetime]nilai hitung integer sebagai kutu, jadi saya menggunakan nilai centang hardcoded dari NTP epoch, kemudian mengurangkannya dari nilai centang waktu UTC saat ini (nilai asli yang secara bersamaan ditugaskan ke $d).

Untuk membuat nilai centang hardcode yang lebih kecil, saya mengambil beberapa nol (9 dari mereka) dan dibagi dengan 98, lalu kalikan dengan 98e9(98 * 10 9 ).

Hasil dari pengurangan itu adalah nilai dalam tick sejak NTP epoch. Itu akan dibagi dengan 1e8(bukan 1e9, untuk alasan yang akan jelas dalam sekejap) untuk mendapatkan nilai dalam hitungan detik (semacam) sejak NTP zaman. Ini akan lebih kecil dengan faktor 10, sebenarnya.

Mengambil dokumen dari IETF, daripada membaginya menjadi garis-garis terlebih dahulu, kemudian memproses garis-garis dengan stempel waktu, saya memutuskan untuk membagi pada kedua jeda baris dan TABkarakter, karena itulah yang muncul setelah cap waktu. Karena satu baris yang salah dalam file, itu saja akan menyertakan stempel waktu tambahan yang tidak kita inginkan. Garisnya terlihat seperti ini:

#@	3707596800

Jadi saya mengubah regex untuk dipisah [^@]\t(karakter apa pun yang tidak @diikuti oleh a TAB) yang berfungsi untuk mengecualikan garis itu, tetapi juga akhirnya menghabiskan yang terakhir 0di setiap stempel waktu.

Itu sebabnya saya membagi 1e8dan tidak 1e9, untuk menjelaskan yang hilang 0.

Stempel waktu saat ini dicentang untuk melihat keberadaannya di dalam daftar stempel waktu lompatan kedua yang dikebiri. Seluruh proses yang saya jelaskan ini ada di dalam array accessor [], sehingga nilai yang dihasilkan [bool]akan digabung menjadi 0( $false) atau 1( $true). Array tempat kami mengindeks berisi dua elemen: string format untuk menampilkan waktu, dan hardcoded 23:59:60. Kebenaran dari perbandingan yang disebutkan di atas menentukan mana yang akan dipilih, dan itu dimasukkan ke dalam operator format -fdengan tanggal saat ini ditugaskan sebelumnya $dsebagai parameternya.

briantis
sumber
Apa ini mencetak yang kedua setelah satu detik? Saya dapat mengikuti logika untuk detik kabisat, tetapi tidak yakin saya dapat mengikuti logika untuk waktu di kedua sisi. (Apakah Windows secara alami menampilkan detik kabisat dan detik berikutnya sebagai 00:00:00?)
@ ais523 akan menampilkan detik setelah detik kabisat apa pun waktu sistemnya. Windows tidak tahu tentang lompatan detik, sehingga jam akan cepat 1 detik hingga diperbaiki dengan pengaturan sinkronisasi atau manual. Mengingat persyaratan yang saya tidak bisa benar-benar menyesuaikan untuk itu, karena tidak mungkin untuk menentukan apakah waktu sistem sudah benar atau tidak tanpa menggunakan sumber waktu eksternal, yang dilarang. Tentang yang terbaik yang bisa saya lakukan adalah menambahkan kode ke ini yang memaksa sinkronisasi NTP setelah mencetak waktu, yang tentu saja bisa gagal (kesalahan jaringan, tidak ada set sumber waktu, dll), jika itu diizinkan.
briantis