Welcome, guest | Sign In | My Account | Store | Cart

This software gets the date from a naval time server and updates the system clock for posix OS supporting the "date" command. It also requires an internet connection.

WARNING: It will not work if your system clock is already off by more than 1 month.

TIP: Use kcron to schedule this script on a periodic basis.

Python, 89 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#!/usr/bin/python
#
# File:   nts_sync.py
# Author: Jason Letbetter
# Date:   8/24/2006
#
# This software gets the date from a naval time server and updates the system
# clock for posix OS supporting the "date" command.  It also requires an
# internet connection.
#
# WARNING: It will not work if your system clock is already off by more than
# 1 month.
#
# TIP: Use kcron to schedule this script on a periodic basis.
#
# Example:
# jason@gummybear:~$ nts_sync.py
# Before update: Sat Aug 26 08:48:41 CDT 2006
# Updating to: Sat Aug 26 13:48:41 UTC 2006
# After update: Sat Aug 26 08:48:41 CDT 2006
#



import sys, os, re, urllib2



def main(argv):
    # Print current date
    sys.stdout.write('Before update: ')
    sys.stdout.flush()
    os.system('date')
    # Update date from naval server
    date = GetDate()
    sys.stdout.write('Updating to: ')
    sys.stdout.flush()
    os.system('sudo date -u %s' % date)
    # Print updated date
    sys.stdout.write('After update: ')
    sys.stdout.flush()
    os.system('date')

    

def GetLocalYear(svrMo):
    # Use the local machine's year b/c naval server doesn't have it
    i,o = os.popen4('date')	
    date = o.read()
    yr = int(date[-5:-1],10)
    # TRICKY: We have to be careful around January 1st
    svrMo = int(svrMo)
    locMo = int(monthMap[date[4:7]])
    # Assume local machine is slow and its near Jan 1st
    if svrMo == 1 and locMo == 12:
        yr+=1
    # Assume local machine is fast and its near Jan 1st
    elif svrMo == 12 and locMo == 1:
        yr-=1
    return str(yr)

        
    
def GetDate():
    # Read date from naval time server (tax payers only ;^)
    url = urllib2.urlopen('http://tycho.usno.navy.mil/cgi-bin/timer.pl')
    text = url.read()    
    # Parse text to get UTC date strings
    regx = r'([a-z,A-Z,]+)\.\s+(\d+)\,\s+(\d+):(\d+):(\d+)\s+UTC'
    mo, da, hr, mi, se = re.search(regx, text).groups()
    # Compute month number from abbreviation
    mo = monthMap[mo]
    # Get the year from our local clock
    yr = GetLocalYear(mo)
    # Return the proper date format
    return mo+da+hr+mi+yr+'.'+se



monthMap = {
    'Jan':  '01', 'Feb':  '02', 'Mar':  '03', 'Apr':  '04',
    'May':  '05', 'Jun':  '06', 'Jul':  '07', 'Aug':  '08',
    'Sep':  '09', 'Oct':  '10', 'Nov':  '11', 'Dec':  '12'
    }
        
        
        
if __name__ == '__main__':
    main(sys.argv[1:])

I wrote this b/c I have a mythtv server w/ a bad clock that slowly gains time. This was causing me to miss the end of my recorded broadcasts.

I scheduled this script to run every night (using kcron). Its difficult to quantify what the worst case error is, but it seems to fix my problem.

I wanted a time server that supported seconds and maintains a consistent output format. After briefly searching for time servers, I chose the naval time server.

The problem w/ the naval time server is that it doesn't show the year. So I get the year from the local clock. This gets tricky around December 31st at midnight. The code deals with the problem by assuming your local clock is no more than 1 month off.

If you know a time server that supports seconds and year feel free to modify the script and post your patch.