#Python/pyClasses/Stopwatch.py #Matthew Ellison # Created: 01-27-19 #Modified: 07-19-20 #This is a class that is used to time program run times """ Copyright (C) 2020 Matthew Ellison This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . """ import time import math class Stopwatch: #Initialize the class and all the variables you will need def __init__(self): self.timeStarted = 0.0 #This variable holds the time that the start function was called self.timeStopped = 0.0 #This variable holds the time that the stop function was called self.started = False #This variable holds true after the start function has been called self.finished = False #This variable holds true after the start and stop functions have been called #Save the time at this point. Simulates starting a stopwatch def start(self): self.started = True self.finished = False self.timeStarted = time.perf_counter_ns() #Save the time at this point. Simulates stopping a stopwatch def stop(self): #If the stopwatch has been started then you record the stopping time if(self.started): self.timeStopped = time.perf_counter_ns() self.finished = True #Otherwise just ignore the function call #Returns the difference between two times, usually start and stop times, but can be start time and now #Simulates looking at the stopwatch; it can still be running when you look at it def getTime(self): #If the start and stop function have been called then calculate the time between the calls if(self.finished): return (self.timeStopped - self.timeStarted) #If start was called but not stop calculate the time between start and now. Simulates looking at the watch while still running elif(self.started): return (time.perf_counter_ns() - self.timeStarted) #If start was never called return a negative number. In this context time can never be negative else: return -1 #Return a specific resolution of time. This is done as a floating point number #Returns the result of getTime() in terms of nanoseconds def getNanoseconds(self): return self.getTime() #Returns the result of getTime() in terms of microseconds def getMicroseconds(self): micro = self.getTime() if(micro < 0): return micro else: return (micro / 1000) #Returns the result of getTime() in terms of milliseconds def getMilliseconds(self): milli = self.getTime() if(milli < 0): return milli else: return (milli / 1000000) #Returns the result of getTime() in terms of seconds def getSeconds(self): second = self.getTime() if(second < 0): return second else: return (second / 1000000000) #Returns the result of getTime() in terms of minutes def getMinutes(self): minute = self.getTime() if(minute < 0): return minute else: return (minute / 60000000000) #Returns the result of getTime() in terms of hours def getHours(self): hour = self.getTime() if(hour < 0): return hour else: return (hour / 3600000000000) #Returns a string with the result of getTime() at the appropriate resolution def getString(self): #Get the time return Stopwatch.getStr(self.getTime()) #Reset the timer so it can be used again def reset(self): self.timeStarted = 0.0 self.timeStopped = 0.0 self.started = False self.finished = False def __str__(self): return self.getString() def __add__(self, other): return self.getString() + other def __radd__(self, other): return other + self.getString() @staticmethod def getStr(time: float) -> str: #Divide by 1000 until you reach an appropriate resolution or run out of types of seconds resCnt = 0 while((time >= 1000) and (resCnt < 3)): time /= 1000 resCnt += 1 #If the resolution counter reached 3 we may need to change to minutes or hours if(resCnt == 3): #Check if seconds is low enough resolution if(time >= 120): #If not, change it to minutes time /= 60 resCnt += 1 #Check if minutes is low enough resolution if(time >= 120): #If not, change it to hours time /= 60 resCnt += 1 #Create a string with the number at ___.___ resolution timeString = "" #If nanoseconds was used we don't need the fractional part if(resCnt == 0): timeString = str(time) + ' ' else: timeString = "{0}.{1:03d} ".format(math.floor(time), round((time % 1) * 1000)) #Determine the resolution of the number and add the appropriate word if(resCnt == 0): timeString += "nanoseconds" elif(resCnt == 1): timeString += "microseconds" elif(resCnt == 2): timeString += "milliseconds" elif(resCnt == 3): timeString += "seconds" elif(resCnt == 4): timeString += "minutes" elif(resCnt == 5): timeString += "hours" else: timeString = "error" #Return the string return timeString