For a project I'm working on we need a basic time holder class. This is written in CircuitPython, which is a stripped down version of CPython that's missing a number of libraries, including the whole datetime library.
The class definition is as follows. Note that TimeDelta is very similar, it also holds a second and day count, but is meant to represent a duration rather than a single point in time. Thus a different class for the different semantic meaning.
__hms_to_secs() and __ymd_to_days() do exactly what their names suggest they ought to.
class TimeStamp:
def __init__(self, year = 2000, month = 1, day = 1, hours = 0, minutes = 0, seconds = 0):
self.seconds = __hms_to_secs(hours, minutes, seconds)
self.days = __ymd_to_days(year, month, day)
self.normalize()
def normalize(self):
if self.seconds < 0 or self.seconds >= 86400:
day_error = self.seconds // 86400
self.seconds -= day_error * 86400
self.days += day_error
return self
def __add__(self, rhs)
return (TimeStamp(self.days + rhs.days, 0, 0, self.seconds + rhs.seconds) if isinstance(rhs, TimeDelta) else TimeDelta(self.days, 0, 0, self.seconds + rhs)).normalize()
def __sub__(self, rhs)
return (TimeDelta(self.days - rhs.days, 0, 0, self.seconds - rhs.seconds) if isinstance(rhs, TimeDelta) else TimeDelta(self.days, 0, 0, self.seconds - rhs)).normalize()
The one thing I'm curious about is the normalize() method. By both modifying self and returning it as well, it allows both
time_stamp.normalize()
and
return temporary_time_stamp.normalize()
to work like you'd expect. But as a relative newcomer to Python I have no idea if this is considered good style. Also observations on __add__() and __sub__() are welcome. Is there a preference for longer "do it all" statements, or for breaking them up into two or more bite sized lines? The intention is to offer two overloads, either adding a TimeDelta or a raw count of seconds.
As a 40 year career C/C++ programmer, overloading based on parameter type is second nature to me. I miss it a lot in Python, which can't do it due to the fact it's duck-typed. So I've taken to doing the overload resolution at run-time.