Computing delta time in DSL Script

I’m trying to create a DSL script in the OH3.2 UI to check if the time since the previous run of the script has exceeded some value. Basically I want a cool down period where the rule body won’t run again until some time has passed. In researching time calculations and comparisons, I found:

and was trying to follow the line used to compute time since epoch in ms:>

// Get epoc from DateTimeType
val Number epoc = (MyDateTimeItem.state as DateTimeType).calendar.timeInMillis

My exact line from the rule is:

val Number TimeoutOverMs = (LastMailOpenTime.state as DateTimeType).calendar.timeInMillis + 1800000

where LastMailOpenTime is a DateTimeItem previously set on the the last run.

When this rule executes, it generates an error:

2022-02-22 12:30:21.355 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID ‘75ab3c8c-db87-4c68-a398-1be4367ad397’ failed: val Number TimeoutOverMs = (LastMailOpenTime.state as DateTimeType). ___ calendar.timeInMillis + 1800000;

  1. The method or field calendar is undefined for the type DateTimeType; line 1, column 68, length 8

I don’t know if things have changed since the article was written in 2017 or something else. Looking for help on how to solve this or a better way of implementing it. Thanks!

That’s a really old post and, as it says, that post has long since been replaced by the official docs. There are better ways to do this specific thing now and even way back then messing with epoch was not the nest approach.

Don’t mess with epoch. It only results in harder to understand code. Use the date times themselves or use Duration.

If you want 30 minutes timeout using ZonedDateTime…

if(MyDateTimeItem.state.getZonedDateTime.plusMinutes(30).isAfter(now)) {

That won’t run the if until it has been at least 30 minutes since the time in MyDateTimeItem.

Using a Duration:

if(Duration.between(MyDateTimeItem.state.getZonedDateTime, now).compareTo(Duration.ofMinutes(30)) > 0) {

That won’t run unless the amount of time between now and the time in MyDateTimeItem is more than 30 minutes.

It’s far easier to read and understand what’s going on. You don’t even need a calculator to understand that 1800000 is 30 minutes.

1 Like

Another approach is to use an Item for a “blocking flag”. Test Item state before doing task. if ok set the Item as task is run, set up the Item to self-expire back to unset,

Thanks for the quick response Rich, I just tried the first suggestion:

if(LastMailOpenTime.state.getZonedDateTime.plusMinutes(30).isAfter(now)) {
getActions(“mail”, “mail:smtp:gmail”).sendMail(“r@g.com”,“Mailbox open alert”,“The mailbox was opened. Maybe you’ve finally got mail!”)
LastMailOpenTime.sendCommand(new DateTimeType(now))
FrontHallLightSwitch_Switch.sendCommand(ON)
}
which results in the following error:
==> /var/log/openhab/openhab.log <==

2022-02-22 13:50:49.531 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID ‘75ab3c8c-db87-4c68-a398-1be4367ad397’ failed: if(LastMailOpenTime.state. ___ getZonedDateTime.plusMinutes(30).isAfter(now)) {

getActions(“mail”, “mail:smtp:gmail”).sendMail(“r@g.com”,“Mailbox open alert”,“The mailbox was opened. Maybe you’ve finally got mail!”)

LastMailOpenTime.sendCommand(new DateTimeType(now))

FrontHallLightSwitch_Switch.sendCommand(ON)

}

The method or field getZonedDateTime is undefined for the type State; line 1, column 26, length 16

Help!

Have you found the forum search feature?

Searching for

led to

Got it working. Thanks for the help. I have tried searching the forums, but that has often taken me down rabbit holes that lead (as happened per my original post) to information that is not or is no longer correct.