Shame on me, but I need to refresh my rule ability… let’s say I have something like this
How do compare two times so I know how many seconds is between those?
Do I need convert DateTime states to something to be able to substract them? cos this is not working
Things
DateTime myTime_on
DateTime myTime_off
Text myPeriod
Rule
rule "compare times"
when
myItem received update
then
val lastON = myTime_on.state
val lastOFF = myTime_off.state
val diff = lastOFF - lastON
postUpdate(myPeriod, diff)
end
val lastOn = (myTime_on.state as DateTimeType).zonedDateTime.timeInMillis
val lastOff = (myTime_off.state as DateTimeType).zonedDateTime.timeInMillis
val diff = (lastOff - lastOn) / 1000
It depends on what you’ve written your rule in. With scripted automation, Jython and the helper libraries, you can use the core.date.seconds_between function…
from core.log import logging, LOG_PREFIX#, log_traceback
from core.date import seconds_between
LOG = logging.getLogger("{}.TEST".format(LOG_PREFIX))
LOG.warn(seconds_between(items["Virtual_DateTime_1"], items["Virtual_DateTime_2"]))
However, java.time.temporal.ChonoUnit provides something similar…
from java.time.temporal.ChronoUnit import SECONDS
from core.log import logging, LOG_PREFIX#, log_traceback
LOG = logging.getLogger("{}.TEST".format(LOG_PREFIX))
LOG.warn(SECONDS.between(items["Virtual_DateTime_1"].zonedDateTime, items["Virtual_DateTime_2"].zonedDateTime))
This can also be used in the rules DSL…
import java.time.temporal.ChronoUnit
rule "Test DSL rule"
when
System started
then
logWarn("Rules", "Test: Start")
logWarn("Rules", "{}", ChronoUnit.SECONDS.between((Virtual_DateTime_1.state as DateTimeType).zonedDateTime, (Virtual_DateTime_2.state as DateTimeType).zonedDateTime))
logWarn("Rules", "Test: End")
end
val lastOn = (ItemON.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli
val lastOff = (itemOFF.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli
val diff = (lastOff - lastOn) / 1000
logInfo("->> one", diff.toString)
logInfo("->> two", "{}", ChronoUnit.SECONDS.between((itemOFF.state as DateTimeType).zonedDateTime, (itemON.state as DateTimeType).zonedDateTime))
and physical device console
21:55:55 MQT: home/test/sensor/PIR = ON
21:56:48 MQT: home/test/sensor/PIR = OFF
so, If I did not missed math in school that’s exactly 53s. That means second approach calculates it correctly, but first is somehow calculating only 25s?
few moments later I’ve got this
22:01:45 MQT: home/test/sensor/PIR = ON
22:02:39 MQT: home/test/sensor/PIR = OFF
Both your failing and successful rules are secret, this makes it difficult to comment constructively.
In the skeleton example at the top, the rule is triggered by one Item updating, but the timestamps are derived from other Items which we have no way of knowing how or when they get updated.
In the later snippet you posted with two methods, each method fetches its ‘data’ independently from Items. There is no guarantee that these Items do not changed inbetween. It’s not a fair test.