Ignition has no concept of "Duration" in its type system (I'm not counting datetimes that you treat like durations), but Java does. For this reason, I like using the java.time.Duration class for all my duration needs.
The Duration class has everything I need, but time arithmetic (with both java.util.Date, Ignition's datetime type, and java.time.Duration) still has to be done with functions instead of operators. I want to be able to write my_date = my_prev_date + my_duration
, and weighted_duration = first_duration * 0.75 + second_duration * 0.25
.
My question is this:
If I import TimeUtils
at the top of any script in my Ignition project, will I then be able to use operators to perform my java.time.Duration
calculations?
My concern is that I will either be unable to write these properties to the imported Jython objects, or that those properties could get dropped between different executions from the same script (scripts are loaded/ran once, but their function definitions may then be used elsewhere).
# Module: TimeUtils
from java.time import Duration
from java.util import Date
NANOS_IN_SEC = 1000000000.0
NANOS_IN_MILLIS = 1000000.0
Duration.__neg__ = Duration.negated
Duration.__abs__ = Duration.abs
def duration__add__(self, other):
if type(other) is Duration:
pass
elif type(other) is Date:
pass
else:
pass
Duration.__add__ = Duration.plus
Duration.__sub__ = Duration.minus
def duration__str__(self):
sign = '-' if self.isNegative() else ''
pos = abs(self) #take the positive to avoid conjugates
hours = pos.toHours()
minutes = pos.toMinutesPart()
seconds = pos.toSecondsPart()
nanoseconds = pos.toNanosPart()
return '{}{:0>2d}:{:0>2d}:{:0>2d}.{:0>9d}' \
.format(sign, hours, minutes, seconds, nanoseconds)
Duration.__str__ = duration__str__
def duration__repr__(self):
return 'Duration({})'.format(str(self))
Duration.__repr__ = duration__repr__
def duration__mul__(self, other):
if type(other) in [int, long, float]:
secs = self.toSeconds() * other
nanos = self.toNanosPart() * other
extra_secs = secs % 1
nanos += NANOS_IN_SEC * extra_secs
secs -= extra_secs
if nanos > NANOS_IN_SEC:
secs += nanos // NANOS_IN_SEC
nanos %= NANOS_IN_SEC
elif nanos < -NANOS_IN_SEC:
secs -= -nanos // NANOS_IN_SEC
nanos = -(-nanos % NANOS_IN_SEC)
return Duration.ofSeconds(long(secs), int(nanos))
else:
raise TypeError("Must multiply by a number")
Duration.__mul__ = duration__mul__
def duration__div__(self, other):
return self * (1.0 / other)
Duration.__div__ = duration__div__
def date__add__(self, other):
if type(other) is Duration:
return system.date.addMillis(self, int(other.toNanos() / NANOS_IN_MILLIS))
else:
raise TypeError('can only add a Duration to a date')
Date.__add__ = date__add__
def date__sub__(self, other):
if type(other) is Duration:
return system.date.addMillis(self, int((-other).toNanos() / NANOS_IN_MILLIS))
elif type(other) is Date:
millisDiff = system.date.millisBetween(other, self)
return Duration.ofMillis(millisDiff)
else:
raise TypeError('can only add a Duration to a date')
Date.__sub__ = date__sub__