5

I am creating a python module that will output the time from a selection of NTP Pool servers to millisecond precision as an exercise in showing how server timestamps vary. Thus far I have been able to print out the origin server timestamp to within a second precision but how can I get the millisecond precision?

ntp_pool = '0.pool.ntp.org', \
       'uk.pool.ntp.org', \
       'ie.pool.ntp.org'

def get_ntp_time():
    for item in ntp_pool:
        call = ntplib.NTPClient()
        response = call.request(item, version=3)
        print(time.ctime(response.orig_time))
eoghan.nolan
  • 53
  • 1
  • 4
  • Answer: don't use ntplib, because it doesn't parse `root_delay` correctly. See https://tools.ietf.org/html/rfc5905 "NTP short format" which is incoherent with https://github.com/Tipoca/ntplib/blob/master/ntplib.py#L185. – Basj Jun 04 '18 at 20:06

2 Answers2

6

The for loop is likely to colour your results since there is time passing in each iteration.

In any case, the ntp response is a timestamp with microsecond accuracy, so the limitation seems to be within time.ctime, which only goes down to second-accuracy

You could use datetime.fromtimestamp instead, and optionally also strftime to make it prettier. My example half-heartedly mimics the output of your existing code.

from datetime import datetime

def get_ntp_time():
for item in ntp_pool:
    call = ntplib.NTPClient()
    response = call.request(item, version=3)
    t = datetime.fromtimestamp(response.orig_time)
    print(t.strftime("%a %b %d %H:%M:%S.%f"))
chinatsu
  • 76
  • 3
1

I think there's something missleading here: response.orig_time is the time of the client that made the request, not that of the server. See IETF RFC5905, p.23: "Origin Timestamp (org): Time at the client when the request departed for the server [...]". An up-to-date version of the code should look something like

import ntplib
from datetime import datetime, timezone

NTP_SERVERS = ['0.pool.ntp.org', 'uk.pool.ntp.org']

for server in NTP_SERVERS:
    client = ntplib.NTPClient()
    response = client.request(server, version=3)
    print(f"server: {server}")
    print(f"client time of request: {datetime.fromtimestamp(response.orig_time, timezone.utc)}")
    print(f"server responded with: {datetime.fromtimestamp(response.tx_time, timezone.utc)}")

...would give me e.g.

server: 0.pool.ntp.org
client time of request: 2019-12-18 13:58:52.224058+00:00
server responded with: 2019-12-18 13:58:51.289734+00:00
server: uk.pool.ntp.org
client time of request: 2019-12-18 13:58:52.314615+00:00
server responded with: 2019-12-18 13:58:51.377655+00:00

Note that depending on how far the signal has to travel, the round trip delay (response.delay) might be significant if you look for the milliseconds.

Community
  • 1
  • 1
FObersteiner
  • 22,500
  • 8
  • 42
  • 72