i am trying to compare dates in items and just can’t work out how to do it. I know this is a common topic and i did a lot of research, but somehow i can’t get the example to work or they don’t apply to my case (found alot for DSL, but sadly can’t transition that to javascript).
I am doing this on Openhab 3.2.0, ECMAScript Edition 11. I edit a rule via the GUI and want to add a script as action in the “then” section.
My goal is to check if year, month and day of the two items (DateTime, Point) is the same.
I am retrieving my items as followed, but don’t know how to proceed for the comparison of the dates (year, month and day).
I can access the content of date1 and date2 (e.g. date1.state) and it was correctly retrieved. I can’t compare them directly as they contain hours, minutes, seconds, … and will never be the same.
I tried “getMonth”, but i get a type error saying that getMonth is not a function. I tried casting it, but got an error as well, so i obv did something wrong.
i did something like this …
var month = (date1.state as DateTimeType).getMonth();
and got “Expected ) but found as” in my log.
I honestly don’t know if i just make some stupid syntax error, missing an import or trying to apply the wrong concept here.
The helper (the thing that provides items.getItem()) almost never gives you the original Java Objects that come from openHAB.
DateTimeType is an openHAB Java class, not JavaScript.
In JavaScript it is very rare that you’d need to ever cast something to another type. It’s really good at handling that sort of thing for you.
So you almost never will be in a position to cast something you got from the helper library to something that is a Java class.
So what do you get back from items.getItem('date1_item')? Looking at the docs we find
.getItem(name, nullIfMissing) ⇒ Item
OK, so what’s Item? Again, looking at the docs a little further down we see Item. There we see that Item.state returns
.state ⇒ String
So date1.state is a String, not a DateTimeType nor anything that can be converted to any sort of date time by casting. Most of the time that doesn’t matter because even if you have a number, you can do math with the String representation of that number without worry (see 3). But DateTime Items are different. You really do want the original DateTimeType. Looking at the docs some more we find rawState
.rawState ⇒ HostState
This is the original Java Item’s state. But there is no getMonth() method on the openHAB Java DateTimeType (see DateTimeType (openHAB Core 4.2.0-SNAPSHOT API)). In no language supported by openHAB could you ever have cast an Item’s state to DateTimeType and call .getMonth() on it. You need to get the raw ZonedDateTime from it. And you’ll see a getZonedDateTime() method on the DateTimeType. From there you can access anything supported by ZonedDateTime (Java SE 11 & JDK 11 ).
Not only solves this my current problem, but also helps me alot understanding how things are implemented and how they work together! Thanks for devoting your time explaining it in that level of detail!
How would one go about setting a DateTime-item to the ZonedDateTime?
I tried:
var zdt = time.ZonedDateTime.now(); items.getItem("myItem").postUpdate(zdt);
var zdt = time.ZonedDateTime.now().toISOString(); items.getItem("myItem").postUpdate(zdt);
var zdt = time.ZonedDateTime.now().toString; items.getItem("myItem").postUpdate(zdt);
But all came back with errors. I did also try: var dt = new Date().toISOString(); items.getItem("myItem").postUpdate(dt); and that gave me 2022-05-30T00:49:41.760+0000 in my item. However, I did expect 2022-05-30T02:49:41.760+0200
I read about toLocalTime() or something similar but this is not the same. For the rule I am designing at the moment it is not a problem but there is something going on with DST in combination with Local Time.
OH 3.2, scripttype is ECMA 11 (2021).
Item = DateTime type
rule:
var zdt = time.ZonedDateTime.now();
items.getItem("ducoBox_1_expire").sendCommand(zdt);
Log:
2022-06-01 00:57:30.065 [WARN ] [ab.core.internal.events.EventHandler] - Creation of event failed, because one of the registered event factories has thrown an exception: Error getting class for simple name: '$ProxType' using package name 'org.openhab.core.library.types.'.
java.lang.IllegalArgumentException: Error getting class for simple name: '$ProxType' using package name 'org.openhab.core.library.types.'.
at org.openhab.core.items.events.ItemEventFactory.parseSimpleClassName(ItemEventFactory.java:183) ~[?:?]
at org.openhab.core.items.events.ItemEventFactory.parseType(ItemEventFactory.java:158) ~[?:?]
at org.openhab.core.items.events.ItemEventFactory.createCommandEvent(ItemEventFactory.java:109) ~[?:?]
at org.openhab.core.items.events.ItemEventFactory.createEventByType(ItemEventFactory.java:78) ~[?:?]
at org.openhab.core.events.AbstractEventFactory.createEvent(AbstractEventFactory.java:53) ~[?:?]
at org.openhab.core.internal.events.EventHandler.createEvent(EventHandler.java:131) ~[?:?]
at org.openhab.core.internal.events.EventHandler.handleEvent(EventHandler.java:106) ~[?:?]
at org.openhab.core.internal.events.EventHandler.handleEvent(EventHandler.java:84) ~[?:?]
at org.openhab.core.internal.events.ThreadedEventHandler.lambda$0(ThreadedEventHandler.java:67) ~[?:?]
at java.lang.Thread.run(Thread.java:829) [?:?]
Caused by: java.lang.ClassNotFoundException: org.openhab.core.library.types.$ProxType cannot be found by org.openhab.core_3.2.0
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:519) ~[org.eclipse.osgi-3.16.300.jar:?]
at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:170) ~[org.eclipse.osgi-3.16.300.jar:?]
at java.lang.ClassLoader.loadClass(ClassLoader.java:522) ~[?:?]
at java.lang.Class.forName0(Native Method) ~[?:?]
at java.lang.Class.forName(Class.java:315) ~[?:?]
at org.openhab.core.items.events.ItemEventFactory.parseSimpleClassName(ItemEventFactory.java:179) ~[?:?]
... 9 more
If I change the rule to:
var zdt = time.ZonedDateTime.now();
var regex = new RegExp(/.*(?=\[SYSTEM\])/gm);
var part = regex.exec(zdt);
part = part[0];
console.log(zdt + " " + part);
items.getItem("ducoBox_1_expire").sendCommand(part);
The item is updated correctly and I get in the log:
OK, postUpdate and sendCommand always requires a String. So you’d never be able to just send a ZoneDateTime as a command.
It’s supposed to be able to parse the default toString() of the ZonedDateTime but that doesn’t seem to be working due to how the timezone is being represented. But it does appear to work with a LocalDateTime.