How should an accumulator in a Python clock be handled correctly?

259 Views Asked by At

I'm writing a small clock object in Python that can be started, stopped and reset. I'm having difficulty knowing how to keep track of the accumulation of time correctly. Right now, the way the update procedure is written, the clock accumulates too much time (because of calls to the update method). I'm not sure how to write this such that it accumulates the correct time.

import time
import datetime

class Clock(object):

    def __init__(
        self,
        name  = None,
        start = True
        ):
        self._name  = name
        self._start = start # Boolean start clock on instantiation
        # If a global clock list is detected, add a clock instance to it.
        if "clocks" in globals():
            clocks.add(self)
        self.reset()
        if self._start:
            self.start()

    def start(self):
        self._startTime = datetime.datetime.utcnow()

    def stop(self):
        self._startTime = None

    # Update the clock accumulator.
    def update(self):
        self.accumulator += (
            datetime.datetime.utcnow() - self._startTime
        )

    def reset(self):
        self.accumulator = datetime.timedelta(0)
        self._startTime  = None

    # If the clock has a start time, add the difference between now and the
    # start time to the accumulator and return the accumulation. If the clock
    # does not have a start time, return the accumulation.
    def elapsed(self):
        if self._startTime:
            self.update()
        return(self.accumulator)

    def time(self):
        return(self.elapsed().total_seconds())

clock = Clock()
print clock.time()
print "starting"; clock.start()
for i in range(4):
    time.sleep(3)
    print clock.time()
print "stopping"; clock.stop()
for i in range(4):
    time.sleep(3)
    print clock.time()
print "starting"; clock.start()
for i in range(4):
    time.sleep(3)
    print clock.time()
print "resetting"; clock.reset()
print clock.time()
1

There are 1 best solutions below

1
On BEST ANSWER

If you just add a call to self.start() at the end of update then I think it will work the way you are intending.

The reason you are seeing the issue with the current code is you are adding the total offset from _startTime to now() each time you update, but you only want the difference between now() and when the timer started on the first call. On subsequent calls you want the difference between now() and the previous call to update.