๊ฐ„๋‹จํ•œ NTP ํด๋ผ์ด์–ธํŠธ ์ž‘์„ฑ

์•ˆ๋…•ํ•˜์„ธ์š”, Habrausers์ž…๋‹ˆ๋‹ค. ์˜ค๋Š˜์€ ๊ฐ„๋‹จํ•œ NTP ํด๋ผ์ด์–ธํŠธ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ๋Œ€ํ™”๋Š” ํŒจํ‚ท์˜ ๊ตฌ์กฐ์™€ NTP ์„œ๋ฒ„์˜ ์‘๋‹ต์ด ์ฒ˜๋ฆฌ๋˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ „ํ™˜๋ฉ๋‹ˆ๋‹ค. ์ฝ”๋“œ๋Š” Python์œผ๋กœ ์ž‘์„ฑ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์ œ ์ƒ๊ฐ์—๋Š” ๊ทธ๋Ÿฌํ•œ ์ž‘์—…์— ๋” ์ข‹์€ ์–ธ์–ด๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ „๋ฌธ๊ฐ€๋“ค์€ ์ด ์ฝ”๋“œ์™€ ntplib ์ฝ”๋“œ์˜ ์œ ์‚ฌ์„ฑ์— ์ฃผ๋ชฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ €๋Š” ์ด ์ฝ”๋“œ์—์„œ "์˜๊ฐ์„ ์–ป์—ˆ์Šต๋‹ˆ๋‹ค".

๊ทธ๋ ‡๋‹ค๋ฉด NTP๋ž€ ๋ฌด์—‡์ผ๊นŒ์š”? NTP๋Š” ํƒ€์ž„ ์„œ๋ฒ„์™€ ํ†ต์‹ ํ•˜๊ธฐ ์œ„ํ•œ ํ”„๋กœํ† ์ฝœ์ž…๋‹ˆ๋‹ค. ์ด ํ”„๋กœํ† ์ฝœ์€ ๋งŽ์€ ์ตœ์‹  ๊ธฐ๊ณ„์—์„œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด Windows์˜ w32tm ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค.

NTP ํ”„๋กœํ† ์ฝœ์—๋Š” ์ด 5๊ฐ€์ง€ ๋ฒ„์ „์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ ๋ฒ„์ „ 0(1985, RFC958)์€ ํ˜„์žฌ ๋” ์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผ๋ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ๋Š” 1์ฐจ(1988, RFC1059), 2์ฐจ(1989, RFC1119), 3์ฐจ(1992, RFC1305), 4์ฐจ(1996, RFC2030) ๋“ฑ ์ตœ์‹  ๋ฒ„์ „์ด ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฒ„์ „ 1-4๋Š” ์„œ๋กœ ํ˜ธํ™˜๋˜๋ฉฐ ์„œ๋ฒ„ ์•Œ๊ณ ๋ฆฌ์ฆ˜๋งŒ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

ํŒจํ‚ท ํ˜•์‹

๊ฐ„๋‹จํ•œ NTP ํด๋ผ์ด์–ธํŠธ ์ž‘์„ฑ

๋„์•ฝ ํ‘œ์‹œ๊ธฐ (์ˆ˜์ • ํ‘œ์‹œ)๋Š” ์œค์ดˆ ๊ฒฝ๊ณ ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์ˆซ์ž์ž…๋‹ˆ๋‹ค. ์˜๋ฏธ:

  • 0 - ์ˆ˜์ • ์—†์Œ
  • 1 - ํ•˜๋ฃจ์˜ ๋งˆ์ง€๋ง‰ 61๋ถ„์€ XNUMX์ดˆ์ž…๋‹ˆ๋‹ค.
  • 2 - ํ•˜๋ฃจ์˜ ๋งˆ์ง€๋ง‰ 59๋ถ„์€ XNUMX์ดˆ์ž…๋‹ˆ๋‹ค.
  • 3 - ์„œ๋ฒ„ ์˜ค๋ฅ˜(๋™๊ธฐํ™” ์‹œ๊ฐ„ ์ดˆ๊ณผ)

๋ฒ„์ „ ๋ฒˆํ˜ธ (๋ฒ„์ „ ๋ฒˆํ˜ธ) โ€“ NTP ํ”„๋กœํ† ์ฝœ ๋ฒ„์ „ ๋ฒˆํ˜ธ(1-4)์ž…๋‹ˆ๋‹ค.

๋ชจ๋“œ (๋ชจ๋“œ) โ€” ํŒจํ‚ท ์†ก์‹ ์ž์˜ ์ž‘๋™ ๋ชจ๋“œ์ž…๋‹ˆ๋‹ค. 0๋ถ€ํ„ฐ 7๊นŒ์ง€์˜ ๊ฐ’(๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ž„):

  • 3 - ํด๋ผ์ด์–ธํŠธ
  • 4 - ์„œ๋ฒ„
  • 5 - ๋ฐฉ์†ก ๋ชจ๋“œ

์ง€์ธต (๊ณ„์ธตํ™” ์ˆ˜์ค€) - ์„œ๋ฒ„์™€ ์ฐธ์กฐ ํด๋ก ์‚ฌ์ด์˜ ์ค‘๊ฐ„ ๊ณ„์ธต ์ˆ˜(1 - ์„œ๋ฒ„๊ฐ€ ์ฐธ์กฐ ํด๋ก์—์„œ ์ง์ ‘ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ด, 2 - ์„œ๋ฒ„๊ฐ€ ๋ ˆ๋ฒจ 1์˜ ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ด ๋“ฑ).
ํ’€ ์—ฐ์† ๋ฉ”์‹œ์ง€ ์‚ฌ์ด์˜ ์ตœ๋Œ€ ๊ฐ„๊ฒฉ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ถ€ํ˜ธ ์žˆ๋Š” ์ •์ˆ˜์ž…๋‹ˆ๋‹ค. NTP ํด๋ผ์ด์–ธํŠธ๋Š” ์—ฌ๊ธฐ์—์„œ ์„œ๋ฒ„๋ฅผ ํด๋งํ•  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒ๋˜๋Š” ๊ฐ„๊ฒฉ์„ ์ง€์ •ํ•˜๊ณ , NTP ์„œ๋ฒ„๋Š” ํด๋ง์ด ์˜ˆ์ƒ๋˜๋Š” ๊ฐ„๊ฒฉ์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ’์€ ์ดˆ์˜ ์ด์ง„ ๋กœ๊ทธ์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.
Precision (์ •๋ฐ€๋„)๋Š” ์‹œ์Šคํ…œ ์‹œ๊ณ„์˜ ์ •ํ™•๋„๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ถ€ํ˜ธ ์žˆ๋Š” ์ •์ˆ˜์ž…๋‹ˆ๋‹ค. ๊ฐ’์€ ์ดˆ์˜ ์ด์ง„ ๋กœ๊ทธ์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.
๋ฃจํŠธ ์ง€์—ฐ (์„œ๋ฒ„ ๋Œ€๊ธฐ ์‹œ๊ฐ„)์€ ์‹œ๊ณ„๊ฐ€ NTP ์„œ๋ฒ„์— ๋„๋‹ฌํ•˜๋Š” ๋ฐ ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„(์ดˆ ๋‹จ์œ„)์ž…๋‹ˆ๋‹ค.
๋ฟŒ๋ฆฌ ๋ถ„์‚ฐ (์„œ๋ฒ„ ๋ถ„์‚ฐ) - NTP ์„œ๋ฒ„ ์‹œ๊ณ„์˜ ๊ณ ์ • ์†Œ์ˆ˜์  ์ˆ˜(์ดˆ) ๋ถ„์‚ฐ์ž…๋‹ˆ๋‹ค.
์ฐธ์กฐ ID (์†Œ์Šค ID) - ์‹œ๊ณ„ ID์ž…๋‹ˆ๋‹ค. ์„œ๋ฒ„์— Stratum 1์ด ์žˆ๋Š” ๊ฒฝ์šฐ ref id๋Š” ์›์ž ์‹œ๊ณ„์˜ ์ด๋ฆ„(ASCII ๋ฌธ์ž 4๊ฐœ)์ž…๋‹ˆ๋‹ค. ์„œ๋ฒ„๊ฐ€ ๋‹ค๋ฅธ ์„œ๋ฒ„๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ์ฐธ์กฐ ID์—๋Š” ์ด ์„œ๋ฒ„์˜ ์ฃผ์†Œ๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.
๋งˆ์ง€๋ง‰ 4๊ฐœ ํ•„๋“œ๋Š” ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค. 32๋น„ํŠธ๋Š” ์ •์ˆ˜ ๋ถ€๋ถ„, 32๋น„ํŠธ๋Š” ์†Œ์ˆ˜ ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.
์ฐธ์กฐ - ์„œ๋ฒ„์˜ ์ตœ์‹  ์‹œ๊ณ„.
์œ ๋ž˜ โ€“ ํŒจํ‚ท์ด ์ „์†ก๋œ ์‹œ๊ฐ„(์„œ๋ฒ„์— ์˜ํ•ด ์ž…๋ ฅ๋จ โ€“ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์•„๋ž˜ ์ฐธ์กฐ)
์ˆ˜์‹  โ€“ ์„œ๋ฒ„๊ฐ€ ํŒจํ‚ท์„ ์ˆ˜์‹ ํ•œ ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค.
์ „์†ก โ€“ ํŒจํ‚ท์ด ์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ๋กœ ์ „์†ก๋œ ์‹œ๊ฐ„(ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ž…๋ ฅ, ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์•„๋ž˜ ์ฐธ์กฐ).

๋งˆ์ง€๋ง‰ ๋‘ ํ•„๋“œ๋Š” ๊ณ ๋ ค๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ํŒจํ‚ค์ง€๋ฅผ ์ž‘์„ฑํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

ํŒจํ‚ค์ง€ ์ฝ”๋“œ

class NTPPacket:
    _FORMAT = "!B B b b 11I"

    def __init__(self, version_number=2, mode=3, transmit=0):
        # Necessary of enter leap second (2 bits)
        self.leap_indicator = 0
        # Version of protocol (3 bits)
        self.version_number = version_number
        # Mode of sender (3 bits)
        self.mode = mode
        # The level of "layering" reading time (1 byte)
        self.stratum = 0
        # Interval between requests (1 byte)
        self.pool = 0
        # Precision (log2) (1 byte)
        self.precision = 0
        # Interval for the clock reach NTP server (4 bytes)
        self.root_delay = 0
        # Scatter the clock NTP-server (4 bytes)
        self.root_dispersion = 0
        # Indicator of clocks (4 bytes)
        self.ref_id = 0
        # Last update time on server (8 bytes)
        self.reference = 0
        # Time of sending packet from local machine (8 bytes)
        self.originate = 0
        # Time of receipt on server (8 bytes)
        self.receive = 0
        # Time of sending answer from server (8 bytes)
        self.transmit = transmit

์„œ๋ฒ„์— ํŒจํ‚ท์„ ๋ณด๋‚ด๊ณ  ๋ฐ›์œผ๋ ค๋ฉด ํŒจํ‚ท์„ ๋ฐ”์ดํŠธ ๋ฐฐ์—ด๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
์ด (๋ฐ ์—ญ๋ฐฉํ–ฅ) ์ž‘์—…์„ ์œ„ํ•ด pack() ๋ฐ unpack()์ด๋ผ๋Š” ๋‘ ๊ฐ€์ง€ ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.

ํŒฉ ๊ธฐ๋Šฅ

def pack(self):
        return struct.pack(NTPPacket._FORMAT,
                (self.leap_indicator << 6) + 
                    (self.version_number << 3) + self.mode,
                self.stratum,
                self.pool,
                self.precision,
                int(self.root_delay) + get_fraction(self.root_delay, 16),
                int(self.root_dispersion) + 
                    get_fraction(self.root_dispersion, 16),
                self.ref_id,
                int(self.reference),
                get_fraction(self.reference, 32),
                int(self.originate),
                get_fraction(self.originate, 32),
                int(self.receive),
                get_fraction(self.receive, 32),
                int(self.transmit),
                get_fraction(self.transmit, 32))

์••์ถ• ํ’€๊ธฐ ๊ธฐ๋Šฅ

def unpack(self, data: bytes):
        unpacked_data = struct.unpack(NTPPacket._FORMAT, data)

        self.leap_indicator = unpacked_data[0] >> 6  # 2 bits
        self.version_number = unpacked_data[0] >> 3 & 0b111  # 3 bits
        self.mode = unpacked_data[0] & 0b111  # 3 bits

        self.stratum = unpacked_data[1]  # 1 byte
        self.pool = unpacked_data[2]  # 1 byte
        self.precision = unpacked_data[3]  # 1 byte

        # 2 bytes | 2 bytes
        self.root_delay = (unpacked_data[4] >> 16) +
            (unpacked_data[4] & 0xFFFF) / 2 ** 16
         # 2 bytes | 2 bytes
        self.root_dispersion = (unpacked_data[5] >> 16) +
            (unpacked_data[5] & 0xFFFF) / 2 ** 16 

        # 4 bytes
        self.ref_id = str((unpacked_data[6] >> 24) & 0xFF) + " " + 
                      str((unpacked_data[6] >> 16) & 0xFF) + " " +  
                      str((unpacked_data[6] >> 8) & 0xFF) + " " +  
                      str(unpacked_data[6] & 0xFF)

        self.reference = unpacked_data[7] + unpacked_data[8] / 2 ** 32  # 8 bytes
        self.originate = unpacked_data[9] + unpacked_data[10] / 2 ** 32  # 8 bytes
        self.receive = unpacked_data[11] + unpacked_data[12] / 2 ** 32  # 8 bytes
        self.transmit = unpacked_data[13] + unpacked_data[14] / 2 ** 32  # 8 bytes

        return self

๊ฒŒ์œผ๋ฅธ ์‚ฌ๋žŒ๋“ค์„ ์œ„ํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ - ํŒจํ‚ค์ง€๋ฅผ ์•„๋ฆ„๋‹ค์šด ๋ฌธ์ž์—ด๋กœ ๋ฐ”๊พธ๋Š” ์ฝ”๋“œ

def to_display(self):
        return "Leap indicator: {0.leap_indicator}n" 
                "Version number: {0.version_number}n" 
                "Mode: {0.mode}n" 
                "Stratum: {0.stratum}n" 
                "Pool: {0.pool}n" 
                "Precision: {0.precision}n" 
                "Root delay: {0.root_delay}n" 
                "Root dispersion: {0.root_dispersion}n" 
                "Ref id: {0.ref_id}n" 
                "Reference: {0.reference}n" 
                "Originate: {0.originate}n" 
                "Receive: {0.receive}n" 
                "Transmit: {0.transmit}"
                .format(self)

์„œ๋ฒ„์— ํŒจํ‚ค์ง€ ๋ณด๋‚ด๊ธฐ

ํ•„๋“œ๊ฐ€ ์ฑ„์›Œ์ง„ ํŒจํ‚ท์„ ์„œ๋ฒ„๋กœ ๋ณด๋ƒ…๋‹ˆ๋‹ค. ๋ฒ„์ „, ๋ชจ๋“œ ะธ ์ „์†ก. ์— ์ „์†ก ๋กœ์ปฌ ์‹œ์Šคํ…œ์˜ ํ˜„์žฌ ์‹œ๊ฐ„(1๋…„ 1900์›” 1์ผ ์ดํ›„์˜ ์ดˆ ์ˆ˜), ๋ฒ„์ „ - 4-3 ์ค‘ ํ•˜๋‚˜, ๋ชจ๋“œ - XNUMX(ํด๋ผ์ด์–ธํŠธ ๋ชจ๋“œ)์„ ์ง€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์š”์ฒญ์„ ๋ฐ›์€ ์„œ๋ฒ„๋Š” NTP ํŒจํ‚ท์˜ ๋ชจ๋“  ํ•„๋“œ๋ฅผ ์ฑ„์šฐ๊ณ  ํ•ด๋‹น ํ•„๋“œ์— ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์œ ๋ž˜ ๊ฐ€์น˜ ์ „์†ก, ์š”์ฒญ์— ํฌํ•จ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ณ ๊ฐ์ด ํ˜„์žฅ์—์„œ ์ž์‹ ์˜ ์‹œ๊ฐ„์˜ ๊ฐ€์น˜๋ฅผ ์ฆ‰์‹œ ์ฑ„์šธ ์ˆ˜ ์—†๋Š” ์ด์œ ๋Š” ๋‚˜์—๊ฒŒ ๋ฏธ์Šคํ„ฐ๋ฆฌ์ž…๋‹ˆ๋‹ค. ์œ ๋ž˜. ๊ฒฐ๊ณผ์ ์œผ๋กœ ํŒจํ‚ท์ด ๋Œ์•„์˜ค๋ฉด ํด๋ผ์ด์–ธํŠธ๋Š” 4๊ฐœ์˜ ์‹œ๊ฐ„ ๊ฐ’, ์ฆ‰ ์š”์ฒญ์ด ์ „์†ก๋œ ์‹œ๊ฐ„(์œ ๋ž˜), ์„œ๋ฒ„๊ฐ€ ์š”์ฒญ์„ ๋ฐ›์€ ์‹œ๊ฐ„(์ˆ˜์‹ ), ์„œ๋ฒ„๊ฐ€ ์‘๋‹ต์„ ๋ณด๋‚ธ ์‹œ๊ฐ„(์ „์†ก) ๋ฐ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์‘๋‹ต์„ ๋ฐ›์€ ์‹œ๊ฐ„ - ํƒœ์–ด๋‚˜๋‹ค (ํŒจํ‚ค์ง€์— ์—†์Œ). ์ด ๊ฐ’์„ ์‚ฌ์šฉํ•˜์—ฌ ์ •ํ™•ํ•œ ์‹œ๊ฐ„์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํŒจํ‚ค์ง€ ์ „์†ก ๋ฐ ์ˆ˜์‹  ์ฝ”๋“œ

# Time difference between 1970 and 1900, seconds
FORMAT_DIFF = (datetime.date(1970, 1, 1) - datetime.date(1900, 1, 1)).days * 24 * 3600
# Waiting time for recv (seconds)
WAITING_TIME = 5
server = "pool.ntp.org"
port = 123
    
packet = NTPPacket(version_number=2, mode=3, transmit=time.time() + FORMAT_DIFF)
answer = NTPPacket()
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
    s.settimeout(WAITING_TIME)
    s.sendto(packet.pack(), (server, port))
    data = s.recv(48)
    arrive_time = time.time() + FORMAT_DIFF
    answer.unpack(data)

์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ

์„œ๋ฒ„์˜ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋Š” Raymond M. Smallian(1978)์˜ ์˜ค๋ž˜๋œ ๋ฌธ์ œ์— ๋Œ€ํ•œ ์˜๊ตญ ์‹ ์‚ฌ์˜ ํ–‰๋™๊ณผ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค. โ€œํ•œ ์‚ฌ๋žŒ์€ ์†๋ชฉ์‹œ๊ณ„๊ฐ€ ์—†์—ˆ์ง€๋งŒ ์ง‘์—๋Š” ์ •ํ™•ํ•œ ๋ฒฝ์‹œ๊ณ„๊ฐ€ ์žˆ์—ˆ๋Š”๋ฐ ๋•Œ๋•Œ๋กœ ์žŠ์–ด๋ฒ„๋ ธ์Šต๋‹ˆ๋‹ค. ๋ฐ”๋žŒ์„ ํ”ผ์šฐ๋‹ค. ์–ด๋Š ๋‚  ๊ทธ๋Š” ์‹œ๊ณ„๋ฅผ ๋‹ค์‹œ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์„ ์žŠ์–ด๋ฒ„๋ฆฌ๊ณ  ์นœ๊ตฌ๋ฅผ ๋งŒ๋‚˜๋Ÿฌ ๊ฐ€์„œ ๊ทธ์™€ ํ•จ๊ป˜ ์ €๋…์„ ๋ณด๋‚ด๊ณ  ์ง‘์— ๋Œ์•„์™”์„ ๋•Œ ์‹œ๊ณ„๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ๋งž์ถ”์—ˆ์Šต๋‹ˆ๋‹ค. ์—ฌํ–‰ ์‹œ๊ฐ„์„ ๋ฏธ๋ฆฌ ์•Œ์ง€ ๋ชปํ–ˆ๋‹ค๋ฉด ๊ทธ๋Š” ์–ด๋–ป๊ฒŒ ์ด๊ฒƒ์„ ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๊นŒ? ๋Œ€๋‹ต์€ ์ด๋ ‡์Šต๋‹ˆ๋‹ค. โ€œ์ง‘์„ ๋‚˜์˜ค๋ฉด ์‚ฌ๋žŒ์ด ์‹œ๊ณ„ ํƒœ์—ฝ์„ ๊ฐ๊ณ  ๋ฐ”๋Š˜์˜ ์œ„์น˜๋ฅผ โ€‹โ€‹๊ธฐ์–ตํ•ฉ๋‹ˆ๋‹ค. ์นœ๊ตฌ์—๊ฒŒ ์™€์„œ ์†๋‹˜์„ ๋– ๋‚˜๋ฉด์„œ ๊ทธ๋Š” ๋„์ฐฉ ๋ฐ ์ถœ๋ฐœ ์‹œ๊ฐ„์„ ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๊ทธ๊ฐ€ ์–ผ๋งˆ๋‚˜ ์˜ค๋žซ๋™์•ˆ ์ž๋ฆฌ๋ฅผ ๋น„์› ๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ง‘์— ๋Œ์•„์™€ ์‹œ๊ณ„๋ฅผ ๋ณด๋ฉด ๋ถ€์žฌ ๊ธฐ๊ฐ„์„ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด ์‹œ๊ฐ„์—์„œ ์ž์‹ ์ด ๋ฐฉ๋ฌธํ•œ ์‹œ๊ฐ„์„ ๋นผ๋ฉด ๊ทธ๊ณณ์„ ์˜ค๊ฐ€๋Š” ๊ธธ์— ๋ณด๋‚ธ ์‹œ๊ฐ„์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ์†๋‹˜์„ ๋– ๋‚  ์‹œ๊ฐ„์— ๊ธธ์—์„œ ๋ณด๋‚ธ ์‹œ๊ฐ„์˜ ์ ˆ๋ฐ˜์„ ์ถ”๊ฐ€ํ•จ์œผ๋กœ์จ ๊ทธ๋Š” ์ง‘์— ๋„์ฐฉํ•˜๋Š” ์‹œ๊ฐ„์„ ํ™•์ธํ•˜๊ณ  ์ด์— ๋”ฐ๋ผ ์‹œ๊ณ„ ๋ฐ”๋Š˜์„ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐํšŒ๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค.

์„œ๋ฒ„๊ฐ€ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•œ ์‹œ๊ฐ„์„ ์ฐพ์œผ์„ธ์š”.

  1. ํด๋ผ์ด์–ธํŠธ์—์„œ ์„œ๋ฒ„๊นŒ์ง€์˜ ํŒจํ‚ท ์ด๋™ ์‹œ๊ฐ„ ์ฐพ๊ธฐ: ((๋„์ฐฉ - ๋ฐœ์‹ ) - (์†ก์‹  - ์ˆ˜์‹ )) / 2
  2. ํด๋ผ์ด์–ธํŠธ ์‹œ๊ฐ„๊ณผ ์„œ๋ฒ„ ์‹œ๊ฐ„์˜ ์ฐจ์ด๋ฅผ ์ฐพ์œผ์„ธ์š”.
    ์ˆ˜์‹  - ๋ฐœ์‹  - ((๋„์ฐฉ - ๋ฐœ์‹ ) - (์ „์†ก - ์ˆ˜์‹ )) / 2 =
    2 * ์ˆ˜์‹  - 2 * ๋ฐœ์‹  - ๋„์ฐฉ + ๋ฐœ์‹  + ์ „์†ก - ์ˆ˜์‹  =
    ์ˆ˜์‹  - ๋ฐœ์‹  - ๋„์ฐฉ + ์ „์†ก

๋ฐ›์€ ๊ฐ€์น˜๋ฅผ ํ˜„์ง€ ์‹œ๊ฐ„์— ๋”ํ•ด ์ธ์ƒ์„ ์ฆ๊น๋‹ˆ๋‹ค.

๊ฒฐ๊ณผ ์ถœ๋ ฅ

time_different = answer.get_time_different(arrive_time)
result = "Time difference: {}nServer time: {}n{}".format(
    time_different,
    datetime.datetime.fromtimestamp(time.time() + time_different).strftime("%c"),
    answer.to_display())
print(result)

์œ ๋Šฅํ•œ ๋งํฌ.

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€