I think that it has been like this every since jruby was officially adopted by openhab back in 2022 IIRC, and this is supported by the latest helper library version which works and tested on all openHAB versions starting from the latest 3.4.x, 4.0, 4.1, … all the way to 5.0 snapshot.
The reason for this particular case is that Epoch in seconds is the standard in Ruby, supported by Ruby’s native Time class. It also supports fractions for sub-second precision.
irb(main):014> now = Time.now
=> 2025-03-12 08:10:14.17885 +1000
irb(main):015> now + 86400
=> 2025-03-13 08:10:14.17885 +1000
irb(main):016> now + 86400.5
=> 2025-03-13 08:10:14.67885 +1000
So this is extended all the way to ZonedDateTime, Instant, DateTimeType, etc. Here are some more examples, including how it works with Duration, and comparisons.
I could not find this in the docs. Is this info anywhere?
I linked my DateTime item now to this channel but it stays at NULL. The log reports:
Transformation ignored, failed to parse [ | time.ZonedDateTime.ofInstant(time.Instant.ofEpochSeconds(parseInt(input)), time.ZonedId.systemDefault()).toString()]: The transformation pattern must be in the syntax of TYPE:PATTERN or TYPE(PATTERN)
You never mention how or where you are applying this transformation. I assumed as a profile. If you are applying it elsewhere you need to follow the error message and tell it which rules language the transformation is written in.
So, in the MQTT channel, where the item is linked, there is a section Profile. I have selected SCRIPT ECMAScript (ECMAScript 262 Edition 11) as the profile and pasted your suggested code; JS(| time.ZonedDateTime.ofInstant(time.Instant.ofEpochSeconds(parseInt(input)), time.ZonedId.systemDefault()).toString()).
I have also created a tempo String-item and tried doing JS(|(parseInt(input)/2).toString()) to see if had any effect. But nothing yet.
I have upgraded to latest stable. Lots of new things, including this bit. Once I get the hang of it, should be ok
We are getting closer. At least the logs now say something I could elaborate with and the solution is very close but involved a typo.
| time.ZonedDateTime.ofInstant(time.Instant.ofEpochSecond(parseInt(input)), time.ZoneId.systemDefault()).toString() ofEpochSeconds needed to be ofEpochSecond and ZonedId should have been ZoneId.
Overall a big thanks. See, the ‘trick’ with the UI and file based difference wasn’t clear to me. Now all working as expected!
I’m sorry, I got caught up in all the JavaScript, time.ZonedDateTime, time.Instant etc.
If you link your channel directly to a DateTime item, this is all you need to do. DateTimeType has a String constructor that understands epoch seconds, so you don’t need JavaScript and/or a profile:
items/test.items:
DateTime DateTimeTest
Console:
openhab> openhab:update DateTimeTest "1741895780"
Update has been sent successfully.
Result:
2025-03-13 21:05:15.478 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'DateTimeTest' changed from NULL to 2025-03-13T20:56:20.000+0100
Just to extend the explanation in my previous post: In this latest example you have microseconds since epoch, and this is supported as well. If the length of the string is less than 12 characters, seconds are assumed.
The dates are the same, right?
Just as when I move the calendar-item in my calendar to tomorrow, so the DateTime reflect tomorrows date for nextTrashTime and I do:
Why does this equation never result in true? Do I need the same time as well?
And if the syntax is wrong, ie remove the () after toLocalDate, I get for both today and tomorrow a true while only 1 should be true!
Because you can’t use == to compare two Object in JS. You have to use .equals().
var isTrashDay = trashDayDt.toLocalDate().equals(time.ZonedDateTime.now().toLocalDate())
Because JS doesn’t allow operator overloading. Therefore == is strictly a boolean mathematical operator that only works with strings and numbers. If you have anything more complicated than that, such as a joda-js LocalDate Object, you have to call the .equals function.
This is the same reason why you have to use the methods to do math or comparisons with Quantity Objects.
So just FYI, I have added support for converting a time.Instant to time.ZonedDateTime in JS Scripting using time.toZDT.
This will be part of the upcoming openhab-js release, which will provide an even better way to work with Instants:
time.toInstant
You can just to MyItem.sendCommand(time.toInstant(500)) to send a Instant of epoch milli 500 to a DateTime Item.
I have just released openhab-js 5.9.0 that contains these changes