DateTime Conversion (openHAB 3.x)

Unfortunately it is not storing in the local zone:
image

image

image
Only the UI is showing the local time

No, of course not, epoch is in UTC.
openHAB converts from UTC to your local zone for display in user-facing UI.
Raw Item state remains UTC.

So to return to what do you want …?

If you want the time in your Item state in local time, you will have to do that in a transformation. Probably JS, so that it can parse the epoch to UTC, find out your local zone, and then convert UTC to local zone, finally adding local zone indicator to the end

If you want to treat the incoming data as non-epoch, again I think you will need a JS transformation. Parse the “epoch” to a datetime, find out the local current offset and apply it, change the zone indicator to local.

Do you think it is also possible to read the epoch, add the value of 2700 (2 hours) and then parse it to datetime? Is this possible out of the box or is also JS needed? How would the transformation look like with the ∩ chain character?

Sure.
Don’t forget you’ll need to assign some zone or other to your new datetime.
You may need to think about daylight savings time.

I don’t know how you think you can do any adding without some kind of transformation.

I’m not writing it for you. There are plenty of examples around.

I have a problem with DateTime Conversion:
I’d like to use a DateTime Item RolladenControlCalendar_1_start as start for a timer.

RolladenControlCalendar_1_Timer = createTimer(RolladenControlCalendar_1_start, [ |
               Rolladen_Event.sendCommand(RolladenControlCalendar_1.state.toString)
            ])

But get following error

2021-04-18 13:05:09.055 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'calendar-1' failed: An error occurred during the script execution: Could not invoke method: org.openhab.core.model.script.actions.ScriptExecution.createTimer(java.time.ZonedDateTime,org.eclipse.xtext.xbase.lib.Procedures$Procedure0) on instance: null in calenda

Any idea to convert the DateTime in the right format for createTimer?

Hi Daniel, i believe that needs more context. CreateTimer needs a number and some info´s how long etc…

an example:

if (Washingmachine_OpState2.state == MODE_ACTIVE) {

            if(tWashing_Machine === null) {
                logInfo("washing", "Timer created.")
                tWashing_Machine = createTimer(now.plusMinutes(5), [ |
                    Washingmachine_OpState2.postUpdate(MODE_FINISHED)
                    logInfo("washing", "Timer expired. Washing Machine FINISHED.")
                    tWashing_Machine = null
                ])
            }
        }

If you want to start the timer when a certain time has come, you need a comparison of 2 dates first and than start a timer for a certain amount of time ( seconds, minutes, hours … )

Here is a good example how to do date comparison:

or more simple:

val startdate = (RolladenControlCalendar_1_start.state as DateTimeType).getZonedDateTime()

if (now.isAfter(startdate)) {   do stuff ....for example create a timer... 

No, createTimer() requires you to give some particular moment in time. When we use “now + 1” it makes a fixed datetime.

The actual trick is that in OH3 createTimer wants a zonedDateTime type,like most stuff. So the Item state just needs conversion to zdt.

Thanks @rossko57 , just that i get this right:

val expiring = (RolladenControlCalendar_1_start.state as DateTimeType).getZonedDateTime()

RolladenControlCalendar_1_Timer = createTimer(expiring, [ |
               Rolladen_Event.sendCommand(RolladenControlCalendar_1.state.toString)
            ])

gives you a timer that finishes at “expiring” ?

As always in openHAB, try it and see.
createTimer() description -

Thanks, yes works, i saw some alarm clock examples as well. :slight_smile:

perfect works for me.

The documentation is somehow not easy to understand. You’ll only find createTimer(AbstractInstant instant, Procedure procedure): For Datatype AbstractInstant I was not able to find anything that makes sense…

I guess that’s why they threw an example in.

After reading through all this, I do not comprehend these time conversions very well.

My Ecobee items include:

DateTime LastOccuTime "Last Occu [%1$tm/%1$td %1$tH:%1$tM]"

Getting the log error of:

Script execution of rule with UID ‘presence-8’ failed: An error occurred during the script execution: null in presence

I understand the below rule no longer works in OH3 because of datetime changes:

rule "LastMotionOFF"
when
    Item remoteSensors_Ecobee_1_Bedroom_Occupancy changed to OFF or
    Item remoteSensors_Ecobee_2_Kitchen_Occupancy changed to OFF 
then
    switch LastOccuTime.state {
      DateTimeType: {
        var DateTime halfHourAgo = now.minusMinutes(30)
        var DateTime lastKnownMotion = new DateTime((LastOccuTime.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli)
        if (halfHourAgo.isAfter(lastKnownMotion)) {
          LastOccuTime.postUpdate(new DateTimeType(halfHourAgo.toString))
        }
      }
    }
end

Is this format not the correct use of zonedDateTime?

try this:

rule "LastMotionOFF"
when
    Item remoteSensors_Ecobee_1_Bedroom_Occupancy changed to OFF or
    Item remoteSensors_Ecobee_2_Kitchen_Occupancy changed to OFF 
then
    switch LastOccuTime.state {
      DateTimeType: {
        var ZonedDateTime halfHourAgo = now.minusMinutes(30)
        var lastKnownMotion = (LastOccuTime.state as DateTimeType).getZonedDateTime() 
        if (halfHourAgo.isAfter(lastKnownMotion)) {
          LastOccuTime.postUpdate(halfHourAgo.toString())
        }
      }
    }
end

atleast the ZonedDateTime comparison should be ok now. Not sure about DateTimeType: {…} though, could be obsolete.

rule "LastMotionOFF"
when
    Item remoteSensors_Ecobee_1_Bedroom_Occupancy changed to OFF or
    Item remoteSensors_Ecobee_2_Kitchen_Occupancy changed to OFF 
then
        var ZonedDateTime halfHourAgo = now.minusMinutes(30)
        var lastKnownMotion = (LastOccuTime.state as DateTimeType).getZonedDateTime() 
        
        if (halfHourAgo.isAfter(lastKnownMotion)) {
          LastOccuTime.postUpdate(halfHourAgo.toString())
    }
end

I’m also moving to OH3 and I’m stuck with this rule:


rule "Check and Reload ComfoAirQ Homie"
when
    Time cron "0 0/5 * * * ?"
then
    if (vQ_Ventilation_Gateway_Connection_State_Last_Update.state == NULL) {
        logInfo("Check and Reload ComfoAirQ Homie", "vQ_Ventilation_Gateway_Connection_State_Last_Update = NULL");
    } else ( now.minusMinutes(3).isAfter((vQ_Ventilation_Gateway_Connection_State_Last_Update.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli))
    {
        // vEQ_Ventilation_Gateway_Reload_Timer.sendCommand(ON)
        logInfo("homie_rules", "Reload Homie Devices")
        mqttActions.publishMQTT("homie/zehnderq450gateway/controls/reload/set","true", false)
    }
end

I get this error:

Script execution of rule with UID 'comfoair-5' failed: An error occurred during the script execution: Could not invoke method: java.time.
chrono.ChronoZonedDateTime.isAfter(java.time.chrono.ChronoZonedDateTime) on instance: 2021-04-27T13:32:00.385453+02:00[Europe/Amsterdam] in comfoair

So I changed zonedDateTime to getZonedDateTime but the error remains. Who can help me?

try this:

rule "Check and Reload ComfoAirQ Homie"
when
    Time cron "0 0/5 * * * ?"
then

    var Ventilation = (vQ_Ventilation_Gateway_Connection_State_Last_Update.state as DateTimeType).getZonedDateTime()

    if (vQ_Ventilation_Gateway_Connection_State_Last_Update.state == NULL) {
        logInfo("Check and Reload ComfoAirQ Homie", "vQ_Ventilation_Gateway_Connection_State_Last_Update = NULL");
    } 
    
        if (now.minusMinutes(3).isAfter(Ventilation)) {
        // vEQ_Ventilation_Gateway_Reload_Timer.sendCommand(ON)
        logInfo("homie_rules", "Reload Homie Devices")
        mqttActions.publishMQTT("homie/zehnderq450gateway/controls/reload/set","true", false)
    }
end
1 Like

That seems to work. So if I understand correctly, the solution was to convert some of the logic to a variable and use that?

yes, but also convert from a DateTimeType correctly to a ZonedDateTime() at the same time. You could do it in just one line I suspect but this is my preferred option for more clarity in the rule. ( just my 2 cent on this )

3 Likes

I appreciate the suggestions. It has been a learning experience.

Hello folks,
can you please give me a hand how to convert in OH3 this from OH2?

now.toString("dd.MM")

?
now.toInstant.toString(“dd MM”) does not do the jobm nor error either :wink:

Thanks