DateTime issue again

I am having datetime issues again. I tried the following rule that is supposed o close the rollershutters, when the Gardendoor is closed between sunset and sunrise:

rule "LE_Groundfloor_Livingroom_Gardendoor_Close_Close_Rule"
when
     Item LE_Groundfloor_Livingroom_Gardendoor_Lock received update CLOSED
then
    logInfo("Demo","This is a log entry of type Info!")
#    if( now.isAfter(LE_Sunset_Time) && now.isBefore(LE_Sunrise_Time))
    if( now.isBefore(LE_Sunset_Time) && now.isAfter(LE_Sunrise_Time))
        sendCommand(LE_Groundfloor_Livingroom_Gardendoor_Shutter,UP)
end

These are the items used:

DateTime LE_Sunrise_Time       "Sunrise [%1$tH:%1$tM]"  { channel="astro:sun:home:rise#start" }
DateTime LE_Sunset_Time        "Sunset [%1$tH:%1$tM]"   { channel="astro:sun:home:set#start" }

For testing purposed, I inverted the times, so it closes during the day. However, I get

11:26:07.581 [ERROR] [.script.engine.ScriptExecutionThread] - Rule 'LE_Groundfloor_Livingroom_Gardendoor_Close_Close_Rule': An error occured during the script execution: Could not invoke method: org.joda.time.base.AbstractInstant.isAfter(org.joda.time.ReadableInstant) on instance: 2017-06-16T11:26:07.580+02:00

It seems that now does not have the right class, but now.isAfter is a common thing seen in examples.How does this work? I would prefer to keep this very readable object oriented style and not convert to millis().

Also, will this even work, or will sunset change to the next day’s value e.g. at midnight?

if(now isAfter((LE_Sunset_Time.state as DateTimeType).calendar.timeInMillis) ||
   now.isBefore(LE_Sunrise_Time.state as DateTimeType).calendar.timeInMillis)

The first problem is to get the value of an Item you must call .state.

Secondly, the value of a DateTime Item is DateTimeType which is not the same thing as a Joda DateTime which now is. Therefore you can’t use it directly in the call to isBefore and isAfter. You must convert it into a format that Joda DateTime can understand.

Thirdly, as you are already guessing, Astro calculates the sunrise and sunset times at midnight. These times are absolute (i.e. include the date, not just the time of day). Therefore check if now is after sunset but before sunrise will never be true because the sunrise and sunset times you have are for today. For example, if it is after sunset and before midnight today, sunset time will be something like 19:31 2017/06/16 and your sunrise time will be something like 05:46 2017/06/16. In order for the if statement to evaluate to true you need the sunrise time for tomorrow or 05:47 2017/06/17.

But by using || instead of && you will get the behavior you want.

I recommend looking at the Time of Day Design Pattern for doing operations like these.

1 Like

Thanks! I got it working with an additional “new DateTime” inside the isAfter functions, but apparently, the Joda function also understand numbers?

The || is a great idea, though.

You can pass it a Joda DateTime or epoc (i.e. number of milliseconds since midnight 1970/1/1).