OH3 DateTime comparison in Javascript/ECMAscript

I’m looking for a way to compare a DateTime item with the current date.
So I tried:

var ago10secs = new Date(date.getTime() - diff*10000)
var lastAction = new Date(items["LastActionTime"].getTime());

I’d like to create:

  1. the JS-date from 10seconds ago
  2. the JS-date from my DateTime item

so, I can compare them.
I get this in the logs:

2021-01-02 23:15:53.043 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'lastAction' failed: ReferenceError: "date" is not defined in <eval> at line number 3

I’m looking across and I mostly find either some DSL-rules examples or some information, which seems odd or outdated. Thanks for your help!

While looking for an example i have found out that i have somt Date variables still working which makes me wonder…

Anyway i would suggest too use Zoneddatetime, since it has replaced jodatime everywhere.
Here is some sample example code (not tested, except for the Java Type)

// Get the Java Type into ECMA Script
var ZonedDateTime   = Java.type("java.time.ZonedDateTime");

// Do some cool time stuff here
var ago10secs = ZonedDateTime.now().minusSeconds(5)

This maybe could also still work with Date

About the lastAction:

I think you have a typo in there. Try:

var lastAction = new Date(items["LastActionTime"]).getTime();

ZonedDateTime Docs:

Ok i played around a bit.

Here is a working example (i used an existing datetime item from my environment):

var logger          = Java.type('org.slf4j.LoggerFactory').getLogger('org.openhab.rule.' + ctx.ruleUID);

var ago10secs = new Date(new Date() - 10000)
var lastAction = new Date(items["vSunset_Time"])

logger.info("ago10secs = " + ago10secs)
logger.info("lastAction = " + lastAction)

ago10secs = ago10secs.getTime()
lastAction = lastAction.getTime()

logger.info("ago10secs as a number= " + ago10secs)
logger.info("lastAction as a number= " + lastAction)

Log:

[INFO ] [org.openhab.rule.2afe6fd13b]- ago10secs = Sun Jan 03 2021 00:08:01 GMT+0100 (CET)
[INFO ] [org.openhab.rule.2afe6fd13b] - lastAction = Sun Jan 03 2021 16:36:00 GMT+0100 (CET)
[INFO ] [org.openhab.rule.2afe6fd13b] - ago10secs = 1609628881227
[INFO ] [org.openhab.rule.2afe6fd13b] - lastAction = 1609688160000

That should do the trick.

2 Likes

Thanks Jerome,

that works great!

Hi @Confectrician,

I am working on some of my ECMA scripts and try to write a DateTime

now = new Date(new Date() - 10000)

to an item with

event.postUpdate(‘DateTimeItem’, now)

but I get the following error:

Fail to execute action: 1

java.lang.IllegalArgumentException: The argument ‘state’ must not be null.

I think there is a problem I don’t see… Please can you give me a hint?

Hi,

2 things from what i read above:

  1. now is not a good name for a variable since ECMAscript may use it as a keyword itself.
  2. Is the quote above written like this in your rule too?
    If you want to use now as a variable you have to place a var in front te declare it.
var myTimeVariable = new Date(new Date() - 10000)

Thank you for your reply.
But the error still exist…

I have changed my rule to:

var mytime = new Date(new Date() - 10000);
events.postUpdate(“Spuelmaschine_OpStateLastChange”, mytime);
logger.info("now = " + mytime);

But I don‘t know what I am doing wrong. Thank you for your help!

I think I found the solution:

var zdt = Java.type(‘java.time.ZonedDateTime’);
var mytime = zdt.now().toLocalDateTime();
events.postUpdate(“Spuelmaschine_OpStateLastChange”, mytime);

Ok, one step for, and two steps back…
I work on the following rule and don’t get it to work (apart from the message format). The problem is the time calculation:

var logger = Java.type("org.slf4j.LoggerFactory").getLogger("org.openhab.model.script.Rules.Experiments");
var telegramAction = actions.get("telegram","telegram:telegramBot:49b7f025cb");
var duration = Java.type('java.time.Duration');
var zdt = Java.type('java.time.ZonedDateTime');

var jetzt = zdt.now().toLocalDateTime();


MODE_OFF = 0
MODE_STANDBY = 3
MODE_ACTIVE = 2
MODE_FINISHED = 1  

logger.info("Spuelmaschine State changed");

if (itemRegistry.getItem('Spuelmaschine_OpState').getState() == MODE_FINISHED) {
  //Aktualisierung Counter
  var counter = itemRegistry.getItem('Spuelmaschine_counter').getState()  //der counter zählt ab 01.05.2019
  counter = counter + 1
  events.postUpdate("Spuelmaschine_counter", counter);
  //Berechnung der Laufzeit
  var lastAction = itemRegistry.getItem('Spuelmaschine_OpStateLastChange').getState();
  var differenz = (jetzt - lastAction);
  var differenz = duration.between(jetzt, lastAction);
  var laufzeitminuten = Math.round(differenz.getSeconds()/60);
 /* var report = "Status: 1 (Fertig)\n" +
               "Start: " + lastAction.toDateTime.toString(dd-MM-yy HH:mm) + "Uhr \n" +
               "Ende: " + jetzt.toDateTime.toString(dd-MM-yy HH:mm) + "Uhr \n" +
               "Laufzeit: "+ laufzeitminuten + " Min.";
  
  var message = "Spülmaschine fertig:\n\n" + report
  
  //sende Nachricht
  telegramAction.sendTelegram(message); */
}
else if (itemRegistry.getItem('Spuelmaschine_OpState').getState() == MODE_ACTIVE) {
        telegramAction.sendTelegram("Spülmaschine wurde gestartet!")
    }
    // remember last change
events.postUpdate("Spuelmaschine_OpStateLastChange", jetzt)

I get the following error:

2021-02-15 14:26:17.940 [WARN ] [e.automation.internal.RuleEngineImpl] - Fail to execute action: 2

java.lang.ClassCastException: Cannot cast org.openhab.core.library.types.DateTimeType to java.time.temporal.Temporal

at java.lang.Class.cast(Class.java:3605) ~[?:?]

I have no idea how to format the datetime variables. Can somebody give me a hint…