Rule: Calc end time from start time and duration

Hi all,
I would like to calculate an end time from a start time and a duration in a rule.
start time and end time are DateTime items.
duration is a Number item.

I have read all the DateTime explanations and tutorials, but somehow still fail.

Here is my code:

.items:

DateTime  IrrigationStarted   "Bewässerung letzter Start [%1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time>                  // virtual item, rule setting, mapdb persistence
DateTime  IrrigationEndTime   "Bewässerung Ende [%1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time>                           // virtual item, rule setting, mapdb persistence 
Group:Number:SUM gIrrigation_Times "Total Irrigation Time is [%d mins]"

.rules

// does not work: Could not invoke method: org.joda.time.DateTime.plusMinutes(int) on instance: 2019-06-27T21:40:16.535+02:00
IrrigationEndTime.postUpdate(now.plusMinutes(gIrrigation_Times.state as Number) as DateTimeType)
IrrigationEndTime.postUpdate(new DateTimeType(now.plusMinutes(gIrrigation_Times.state as Number)))
IrrigationEndTime.postUpdate(now.plusMinutes(gIrrigation_Times.state as Number).intValue)

// Does not work: Cannot cast from DateTime to DateTimeType
IrrigationEndTime.postUpdate(now.plusMinutes(gIrrigation_Times.intValue) as DateTimeType) 

Maybe I cannot use .plusMinutes here and have to convert the DateTime item to .toEpochMilli, do the sum and convert back?
Any help is appreciated.

Please have a look at this tutorial. Very helpful.

This was one of the tutorials I already looked at, but I will have a deeper look again.

One important thing to realize is that DateTime and DateTimeType are not the same. You need to convert from one to the other. The other is to realize that plusMinutes requires a primitive int, just a Number. Finally, nothing will work if the state of gIrrigation_Times is UNDEF or NULL.

IrrigationEndTime.postUpdate(now.plusMinutes((gIrrigation_Times.state as Number).intValue).toString)

You were pretty close . You were just missing the toString. You can’t set a DateTimeItem using a DateTime, but it can parse the ISO 8601 formatted date String that DateTime outputs by default.

That works, great, thanks, Rich!

  • Just as addition: After reading the tutorial again, I found another (nearly similar) way:
IrrigationEndTime.postUpdate(new DateTimeType(new DateTime(now.millis + (gIrrigation_Times.state as Number).intValue * 60000).toString))

This works as well.

Okay, after updating to OH3, both methods do not work any more.
I have tried many variants, also from https://community.openhab.org/t/datetime-conversion-openhab-3-x/107197, without success.
I get errors like "Could not invoke method: org.openhab.core.model.script.actions.BusEvent.postUpdate(org.openhab.core.items.Item,java.lang.Number) on instance: null in home "
Any idea how to fix it?

Not without seeing the actual lines of code that generate that error. What is meant by “both methods”?

Both methods mean your proposed solution

IrrigationEndTime.postUpdate(now.plusMinutes((gIrrigation_Times.state as Number).intValue).toString)

and my other solution

IrrigationEndTime.postUpdate(new DateTimeType(new DateTime(now.millis + (gIrrigation_Times.state as Number).intValue * 60000).toString))

They worked in 2.5, but do not work in 3.x any more.

I wouldn’t expect the version with DateTime to work, you’ll already know that from the OH3 conversion thread that you read.

What does the other one do? What is the value you are trying to do it with?

OK, well both of those solutions were posted two years ago, more than a year before OH 3 was developed and released.

The examples you need are #3 at the DateTime Conversion (openHAB 3.x) post.

now is a Java ZonedDateTime. The key is now.toLocalDateTime().toString() for the first line.

For the second line there is no Joda DateTime any more. See #7 for how to get epoch (i.e. the old now.millis) and see #2 for how to create a DateTimeType from epoch.

Thanks for your hints.

IrrigationStarted.postUpdate(new DateTimeType())

works, as well as

IrrigationEndTime.postUpdate(DateTimeType.valueOf(now.toLocalDateTime().toString()))

But how do I add the minutes (plusMinutes((gIrrigation_Times.state as Number))?

The same way you did before.

now.plusMinutes(5).toLocalDateTime().toString()

or even

now.toLocalDateTime().plusMinutes(5).toString()

Yes, with your help it finally works!
Small adaption, but now the statement

IrrigationEndTime.postUpdate(now.plusMinutes((gIrrigation_Times.state as Number).intValue).toLocalDateTime().toString())

runs without error.
Thanks for the patience and help!