I wrote a small python2 application to keep track of a watch/clock's
daily rate error. It's a console-only mimic of an Android app that
I use on my phone to track my watch timekeeping.
I wrote it mainly as a thought-experiment rather than as a fully functional
piece of code.
You put the application in a directory specific to the watch and execute it from that
directory. the data from each measurement is stored in a json file in the same directory.
watchcheck.py
- watchcheck.py
#! /usr/bin/env python
## a text-terminal version of the WatchCheck app
## to track error, daily error rate of timepieces.
# auto update?
#
import time
import datetime
import json
def write_file(text):
filename = "logfile.txt"
f = open(filename, 'a+')
timenow = time.strftime("%d/%m/%Y %H:%M:%S", time.gmtime(time.time()))
log = " ".join((timenow, text, "\r\n"))
f.write(log)
f.close()
def get_delta():
print time.strftime("Current Time = %H:%M")
h = time.strftime("%H")
w = raw_input("Watch time %s:" % (h))
print w
date = time.strftime("%Y/%m/%d")
s = date + " " + h +":"+ w +":00"
raw_input("Press enter when seconds = 0 ")
watchtime = time.mktime(datetime.datetime.strptime(s, "%Y/%m/%d %H:%M:%S").timetuple())
record_time = time.strftime("%Y/%m/%d %H:%M:%S")
timenow = time.time()
delta = watchtime - timenow
return record_time,delta
def watch_stat():
try:
saved_error = open('error_list.json')
error_list = json.load(saved_error)
except:
error_list = []
if len(error_list) > 1:
first_record = error_list[0]
latest_record = error_list[-1]
previous_record = error_list[-2]
first_time = first_record[0]
first_delta = first_record[1]
latest_time = latest_record[0]
latest_delta = latest_record[1]
previous_time = previous_record[0]
previous_delta = previous_record[1]
FMT = '%Y/%m/%d %H:%M:%S'
t_latest = datetime.datetime.strptime(latest_time, FMT)
t_previous = datetime.datetime.strptime(previous_time, FMT)
t_first = datetime.datetime.strptime(first_time, FMT)
tdelta = t_latest - t_previous
full_delta = t_latest - t_first
elapsed_time = tdelta.total_seconds()
full_time = full_delta.total_seconds()
print "First record time ", first_time
print "First record delta ", first_delta
print ""
print "Previous record time ", previous_time
print "Previous record delta ", previous_delta
print ""
print "Latest record time " , latest_time
print "Latest record delta ", latest_delta
print ""
print "Overall elapsed time ", full_delta
print "Latest elapsed time ", tdelta
print ""
# Current Error rate
time_error = latest_delta - previous_delta
error_rate = time_error / elapsed_time
daily_rate = error_rate * (60*60*24)
ppm_daily = error_rate * 1000000
# Overall Error rate
total_error = latest_delta - first_delta
average_error_rate = total_error / full_time
average_rate = average_error_rate * (60*60*24)
ppm_overall = average_error_rate * 1000000
print "Latest delta change ", time_error
print "Latest elapsed time %d seconds " % (elapsed_time)
print ""
print "Daily PPM : %0.3f" % ppm_daily
print "Daily rate error: %0.1f s/d " % (daily_rate)
print ""
print "Total Time %d seconds" % (full_time)
print "Total error ", total_error
print "Total PPM : %0.3f" % ppm_overall
print "Total rate error: %0.1f s/d" % (average_rate)
print ""
print "========================================================"
print " Delta : %+0.1f s | Rate : %+0.1f s/d | Average : %+0.1f s/d" % (latest_delta, daily_rate, average_rate)
print "========================================================"
print ""
text = "\t%+0.1f\t\t%+0.1f\t\t%+0.1f" % (latest_delta, daily_rate, average_rate)
write_file(text)
else:
print "No rate yet"
def new_record():
try:
saved_error = open('error_list.json')
error_list = json.load(saved_error)
except:
error_list = []
s,delta = get_delta()
print ""
print "%s \n\nDelta %0.1f seconds" % (s, delta)
last_data=[s,delta]
error_list.append(last_data)
#print error_list
with open('error_list.json', 'wb') as outfile:
json.dump(error_list, outfile)
return
def delete_last():
try:
saved_error = open('error_list.json')
error_list = json.load(saved_error)
except:
error_list = []
error_list.pop()
with open('error_list.json', 'wb') as outfile:
json.dump(error_list, outfile)
return
def menu():
print "Wire2waves WatchCheck....."
print "=========================\n"
print "N : New Record\nD : Delete Last\nS : Stats\nQ : Quit\n"
choice = raw_input("Command > : ").upper()
if choice == "N":
print "New"
new_record()
watch_stat()
menu()
elif choice == "S":
print "Stat"
watch_stat()
menu()
elif choice == "D":
delete_last()
watch_stat()
menu()
elif choice == "Q":
return
else:
print "?"
menu()
menu()
Running it for the first time, with no previous records stored, looks like this:
Wire2waves WatchCheck.....
=========================
N : New Record
D : Delete Last
S : Stats
Q : Quit
Command > : n
New
Current Time = 10:18
Watch time 10:19
19
Press enter when seconds = 0
2022/05/04 10:19:30
Delta -30.2 seconds
and the first time-delta is stored in the error_list.json
file like this:
[["2022/05/04 10:19:30", -30.179980039596558]]
Running it again, after only 10 minutes looks like this:
Command > : n
New
Current Time = 10:30
Watch time 10:30
30
Press enter when seconds = 0
2022/05/04 10:30:30
Delta -30.2 seconds
First record time 2022/05/04 10:19:30
First record delta -30.1799800396
Previous record time 2022/05/04 10:19:30
Previous record delta -30.1799800396
Latest record time 2022/05/04 10:30:30
Latest record delta -30.1998269558
Overall elapsed time 0:11:00
Latest elapsed time 0:11:00
Latest delta change -0.0198469161987
Latest elapsed time 660 seconds
Daily PPM : -30.071
Daily rate error: -2.6 s/d
Total Time 660 seconds
Total error -0.0198469161987
Total PPM : -30.071
Total rate error: -2.6 s/d
========================================================
Delta : -30.2 s | Rate : -2.6 s/d | Average : -2.6 s/d
========================================================
The error_list.json
file now looks like:
[["2022/05/04 10:19:30", -30.179980039596558], ["2022/05/04 10:30:30", -30.199826955795288]]
There's also a small utility called watchstat.py
that reads the error_list.json
file to calculate and
display the data
watchstat.py
- watchstat.py
#! /usr/bin/env python
## a text-terminal version of the WatchCheck app
## to track error, daily error rate of timepieces.
#
import time
import datetime
import json
def watch_stat():
try:
saved_error = open('error_list.json')
error_list = json.load(saved_error)
except:
error_list = []
if len(error_list) > 1:
first_record = error_list[0]
latest_record = error_list[-1]
previous_record = error_list[-2]
first_time = first_record[0]
first_delta = first_record[1]
latest_time = latest_record[0]
latest_delta = latest_record[1]
previous_time = previous_record[0]
previous_delta = previous_record[1]
FMT = '%Y/%m/%d %H:%M:%S'
t_latest = datetime.datetime.strptime(latest_time, FMT)
t_previous = datetime.datetime.strptime(previous_time, FMT)
t_first = datetime.datetime.strptime(first_time, FMT)
tdelta = t_latest - t_previous
full_delta = t_latest - t_first
elapsed_time = tdelta.total_seconds()
full_time = full_delta.total_seconds()
print "First record time ", first_time
print "First record delta ", first_delta
print ""
print "Previous record time ", previous_time
print "Previous record delta ", previous_delta
print ""
print "Latest record time " , latest_time
print "Latest record delta ", latest_delta
print ""
print "Overall elapsed time ", full_delta
print "Latest elapsed time ", tdelta
print ""
# Current Error rate
time_error = latest_delta - previous_delta
error_rate = time_error / elapsed_time
daily_rate = error_rate * (60*60*24)
ppm_daily = error_rate * 1000000
# Overall Error rate
total_error = latest_delta - first_delta
average_error_rate = total_error / full_time
average_rate = average_error_rate * (60*60*24)
ppm_overall = average_error_rate * 1000000
print "Latest delta change ", time_error
print "Latest elapsed time %d seconds " % (elapsed_time)
print ""
print "Daily PPM : %0.3f" % ppm_daily
print "Daily rate error: %0.1f s/d " % (daily_rate)
print ""
print "Total Time %d seconds" % (full_time)
print "Total error ", total_error
print "Total PPM : %0.3f" % ppm_overall
print "Total rate error: %0.1f s/d" % (average_rate)
print ""
print "========================================================"
print " Delta : %0.1f s | Rate : %0.1f s/d | Average : %0.1f s/d" % (latest_delta, daily_rate, average_rate)
print "========================================================"
print ""
else:
print "No rate yet"
watch_stat()
Running watchstat.py on the newly updated error_list.json
gm4slv@laptop:~/watchcheck_damasko $ python watchstat.py
First record time 2022/05/04 10:19:30
First record delta -30.1799800396
Previous record time 2022/05/04 10:19:30
Previous record delta -30.1799800396
Latest record time 2022/05/04 10:30:30
Latest record delta -30.1998269558
Overall elapsed time 0:11:00
Latest elapsed time 0:11:00
Latest delta change -0.0198469161987
Latest elapsed time 660 seconds
Daily PPM : -30.071
Daily rate error: -2.6 s/d
Total Time 660 seconds
Total error -0.0198469161987
Total PPM : -30.071
Total rate error: -2.6 s/d
========================================================
Delta : -30.2 s | Rate : -2.6 s/d | Average : -2.6 s/d
========================================================
watchcheck.py
also creates a log file on each run.
04/05/2022 09:30:30 -30.2 -2.6 -2.6
The fields are “date time”, current error, error in seconds per day since last record, average error in seconds per day since the start.
This mimics the behaviour of the Android Watchcheck app
John Pumford-Green Wed May 4 09:09:09 2022
Page Updated : 02/07/22 13:43 BST