0

I'm making a very simple clock object in Python. I want to be able to instantiate a clock giving it a name and have it record the time it is running for, with pause functionality. I think I've nearly got it, but the pause functionality is giving me some trouble -- the clock continues to accumulate time even when stopped. I think the problem lies in the way the accumulated run time (the _runTime data attribute) is updated (in the method update()). I would welcome assistance in getting this code working sensibly and would welcome any other comments on making the ideas here better.

import time
import datetime

def style_datetime_object(
    datetimeObject = None,
    style = "YYYY-MM-DDTHHMMSS"
    ):
    # filename safe
    if style == "YYYY-MM-DDTHHMMSSZ":
        return(datetimeObject.strftime('%Y-%m-%dT%H%M%SZ'))
    # microseconds
    elif style == "YYYY-MM-DDTHHMMSSMMMMMMZ":
        return(datetimeObject.strftime('%Y-%m-%dT%H%M%S%fZ'))
    # elegant
    elif style == "YYYY-MM-DD HH:MM:SS UTC":
        return(datetimeObject.strftime('%Y-%m-%d %H:%M:%SZ'))
    # UNIX time in seconds with second fraction
    elif style == "UNIX time S.SSSSSS":
        return((datetimeObject - datetime.datetime.utcfromtimestamp(0)).total_seconds())
    # UNIX time in seconds rounded
    elif style == "UNIX time S":
        return(int((datetimeObject - datetime.datetime.utcfromtimestamp(0)).total_seconds()))
    # filename safe
    else:
        return(datetimeObject.strftime('%Y-%m-%dT%H%M%SZ'))

class Clock(object):

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

    def name(
        self
        ):
        return(self._name)

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

    def stop(
        self
        ):
        self._stopTime = datetime.datetime.utcnow()
        self._running  = False
        self.update()

    def startTime(
        self
        ):
        return(style_datetime_object(datetimeObject = self._startTime))

    def update(
        self
        ):
        # If the clock is running, the run time is the difference between the
        # current time and the start time (added to any previously accumulated
        # run time). If the clock is not running, the run time is the difference
        # between the stop time and the start time (added to any previously
        # accumulated run time).
        if self._running:
            if self._runTime:
                self._runTime = self._runTime + datetime.datetime.utcnow() - self._startTime
            else:
                self._runTime = datetime.datetime.utcnow() - self._startTime
        else:
            if self._runTime:
                self._runTime = self._runTime + self._stopTime - self._startTime
            else:
                self._runTime = self._stopTime - self._startTime

    def time(
        self
        ):
        self.update()
        return(self._runTime.total_seconds())

print("create clock")
a = Clock(name = "hello")
print("clock start time: {time}".format(time = a.startTime()))
print("sleep 2 seconds")
time.sleep(2)
print("clock current time (s): {time}".format(time = a.time()))

print

print("create new clock")
b = Clock(name = "world")
print("clock start time: {time}".format(time = b.startTime()))
print("sleep 2 seconds")
time.sleep(2)
print("clock current time (s): {time}".format(time = b.time()))
print("stop clock")
b.stop()
print("sleep 2 seconds")
time.sleep(2)
print("clock current time (s): {time}".format(time = b.time()))
2
  • Giving you what trouble? Be as specific as possible. Commented Dec 10, 2014 at 21:45
  • Sorry - the clock continues accumulating time when it shouldn't. The pause should stop it from accumulating time. I think the problem lies in the way the _runTime data attribute gets updated in the update() method. Commented Dec 10, 2014 at 21:54

1 Answer 1

1

I found your code hard to follow. Here is my (much smaller) clock anyway, may be you can draw some inspiration to implement any lacking feature later.

import datetime

class Clock(object):
    def __init__(self):
        self.reset()
    def reset(self):
        self.accumulator = datetime.timedelta(0)
        self.started = None
    def start_stop(self):
        if self.started:
            self.accumulator += (
                datetime.datetime.utcnow() - self.started
            )
            self.started = None
        else:
            self.started = datetime.datetime.utcnow()
    @property
    def elapsed(self):
        if self.started:
            return self.accumulator + (
                datetime.datetime.utcnow() - self.started
            )
        return self.accumulator
    def __repr__(self):
        return "<Clock {} ({})>".format(
            self.elapsed,
            'started' if self.started else 'stopped'
        )

Tests:

c = Clock()
print c
print "Starting..."; c.start_stop()
for i in range(4):
    time.sleep(2)
    print c
print "Stopping..."; c.start_stop()
for i in range(4):
    time.sleep(2)
    print c
print "Starting..."; c.start_stop()
for i in range(4):
    time.sleep(2)
    print c
print "Resetting..."; c.reset()
print c

Result:

<Clock 0:00:00 (stopped)>
Starting...
<Clock 0:00:02.002085 (started)>
<Clock 0:00:04.004263 (started)>
<Clock 0:00:06.006483 (started)>
<Clock 0:00:08.007675 (started)>
Stopping...
<Clock 0:00:08.007756 (stopped)>
<Clock 0:00:08.007756 (stopped)>
<Clock 0:00:08.007756 (stopped)>
<Clock 0:00:08.007756 (stopped)>
Starting...
<Clock 0:00:10.009876 (started)>
<Clock 0:00:12.012034 (started)>
<Clock 0:00:14.013143 (started)>
<Clock 0:00:16.015291 (started)>
Resetting...
<Clock 0:00:00 (stopped)>
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for your help on that! Your toggling method was particularly clear.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.