พิมพ์เวลาปัจจุบัน…โดยคำนึงถึงวินาทีกระโดด


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และตัวอักษร linebreak ( 0xA) ในสตริง regex เพื่อให้ฉันไม่ต้องหนีพวกเขา (บันทึก 1 byte แต่ละ)

คำอธิบาย

ครั้งที่กำหนด (วินาทีกระโดด) ในแฟ้ม IETF อยู่ในวินาทีตั้งแต่ยุค NTP 1/1/1900 00:00:00ซึ่งเป็น ใน Windows "ติ๊ก" เป็นเพียงหนึ่งในสิบล้านของวินาที (10,000,000 เห็บ / วินาที)

หากคุณเพิ่มจำนวนเต็มไปยัง[datetime]ค่านั้นจะนับค่าจำนวนเต็มเป็น ticks ดังนั้นฉันจึงใช้ค่าขีด hardcoded ของ NTP epoch จากนั้นลบมันออกจากค่า tick ของเวลา UTC ปัจจุบัน (ค่าดั้งเดิมซึ่งถูกกำหนดพร้อมกัน ถึง$d)

เพื่อให้ค่าติ๊ก hardcoded นั้นเล็กลงฉันจึงลบค่าศูนย์ (9 ของพวกเขา) และหารด้วย 98 จากนั้นคูณด้วย98e9(98 * 10 9 )

ผลลัพธ์ของการลบนั้นคือค่าเป็นเห็บนับตั้งแต่ยุค NTP ที่ได้รับการหารด้วย1e8(ไม่ใช่1e9ด้วยเหตุผลที่ชัดเจนในช่วงเวลาหนึ่ง) เพื่อรับค่าเป็นวินาที (เรียงลำดับ) ตั้งแต่ยุค NTP มันจะเล็กลง 10 เท่าจริง

การดึงเอกสารจาก IETF แทนที่จะแยกเป็นบรรทัดแรกจากนั้นประมวลผลบรรทัดด้วยการประทับเวลาฉันตัดสินใจที่จะแยกทั้งตัวแบ่งบรรทัดและTABตัวละครเนื่องจากนั่นคือสิ่งที่เกิดขึ้นหลังจากการประทับเวลา เนื่องจากมีบรรทัดที่ผิดพลาดบรรทัดเดียวในไฟล์เพียงอย่างเดียวนั่นจึงรวมเวลาประทับเพิ่มเติมที่เราไม่ต้องการ บรรทัดมีลักษณะดังนี้:

#@	3707596800

ดังนั้นฉันจึงเปลี่ยน regex ให้แยก[^@]\t(ตัวละครใด ๆ ที่ไม่ได้@ตามมาด้วยTAB) ซึ่งทำงานเพื่อแยกบรรทัดนั้น แต่ท้ายที่สุดก็ใช้เวลานาน0ในแต่ละการประทับเวลา

นั่นเป็นเหตุผลที่ผมหารด้วย1e8และไม่เพื่อบัญชีสำหรับที่ขาดหายไป1e90

การประทับเวลาปัจจุบันมีการตรวจสอบเพื่อดูว่ามีอยู่ในรายการของการประทับเวลาแบบกระโดดครั้งที่สอง กระบวนการทั้งหมดที่ฉันอธิบายนี้อยู่ใน accessor ของอาร์เรย์[]ดังนั้น[bool]ค่าผลลัพธ์จะถูกรวมเข้ากับ a 0( $false) หรือ1( $true) อาร์เรย์ที่เราจัดทำดัชนีไว้มีสององค์ประกอบคือสตริงรูปแบบสำหรับการแสดงเวลาและฮาร์ดโค้ด23:59:60hardcoded ความจริงของการเปรียบเทียบดังกล่าวจะเป็นตัวกำหนดว่าจะเลือกแบบใดและจะถูกป้อนเข้าสู่ตัวดำเนินการรูปแบบ-fโดยมีวันที่ปัจจุบันที่กำหนดไว้ก่อนหน้านี้$dเป็นพารามิเตอร์


สิ่งนี้พิมพ์ครั้งที่สองหลังจากก้าวกระโดดครั้งที่สอง? ฉันสามารถปฏิบัติตามตรรกะเป็นวินาทีกระโดด แต่ไม่แน่ใจว่าฉันสามารถปฏิบัติตามตรรกะครั้งด้านใดด้านหนึ่ง (Windows แสดงทั้งเผ่นวินาทีและวินาทีต่อไปนี้เป็น 00:00:00 หรือไม่)

@ ais523 มันจะแสดงวินาทีหลังจากเผ่นวินาทีตามเวลาของระบบ Windows ไม่ทราบเกี่ยวกับวินาทีกระโดดดังนั้นนาฬิกาจะเร็ว 1 วินาทีจนกว่าจะแก้ไขโดยการตั้งค่าการซิงค์หรือตั้งค่าด้วยตนเอง กำหนดความต้องการที่ฉันไม่สามารถปรับได้เพราะมันเป็นไปไม่ได้ที่จะตรวจสอบว่าเวลาระบบถูกต้องหรือไม่โดยไม่ใช้แหล่งเวลาภายนอกซึ่งถูกแบน เกี่ยวกับสิ่งที่ดีที่สุดที่ฉันสามารถทำได้คือเพิ่มรหัสลงในสิ่งนี้ซึ่งบังคับให้ซิงค์ NTP หลังจากพิมพ์เวลาซึ่งแน่นอนว่าอาจล้มเหลว (ข้อผิดพลาดของเครือข่ายไม่มีการตั้งค่าแหล่งเวลา ฯลฯ ) หากได้รับอนุญาต
ต้มตุ๋น
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.