I’m facing following problem: I do have two String items HzgAnlage_DateString (with value in yyyy-MM-dd pattern like 2016-11-21) and HzgAnlage_TimeString (with value in HH:mm:ss pattern like 21:53:28).
For a comparing rule I’ve tried to build a new DateTime variable using following statement:
import org.openhab.model.script.actions.*
import org.openhab.core.persistence.*
import org.openhab.core.library.types.*
import java.lang.Math
import org.joda.time.*
import java.util.Date
import java.text.SimpleDateFormat
rule "Syncronisation"
when
Item Datum changed
then
...
var DateTime date = DateTime.parse(HzgAnlage_DateString.state + " " + HzgAnlage_TimeString.state, DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"))
...
end
But the OH Designer throws following errors:
- Couldn't resolve reference to JvmType 'DateTime'.
- Couldn't resolve reference to JvmIdentifiableElement 'DateTime'.
- Couldn't resolve reference to JvmIdentifiableElement 'forPattern'.
- Couldn't resolve reference to JvmIdentifiableElement 'DateTimeFormat'.
- Couldn't resolve reference to JvmIdentifiableElement 'parse'.
Does it run? It has been awhile since I’ve used 1.8 Designer so I don’t know if it is having some issues identifying joda.
If something really looks right but Designer is still marking it as wrong, try running it to make sure it really is an error and not just Designer having problems.
The following rule statement does now run though the OH Designer throws a bunch of error messages but the logfile doesn’t and i get a logInfo message:
import org.openhab.model.script.actions.*
import org.openhab.core.persistence.*
import org.openhab.core.library.types.*
import java.lang.Math
import java.util.Date
import java.text.SimpleDateFormat
import org.joda.time.*
import org.joda.datetime.*
rule "Syncronisation"
when
Item Datum changed
then
var DateTime dtHeizungsanlage = parse(HzgAnlage_DateString.state + "T" + HzgAnlage_TimeString.state)
val DateTime dtAktuell = Datum.state
logInfo("DateTime","Heizung=" + dtHeizungsanlage + " *** " + "OH=" + Datum.state)
end
The things is basically I want two compare the two DateTime items and check if (dtHeizungsanlage + 2 minutes) is later then dtAktuell. Therefore i want to use the “isAfter” method but this throws an error in the logfile:
[ERROR] [o.o.c.s.ScriptExecutionThread ] - Error during the execution of rule 'Syncronisation': Could not invoke method: org.joda.time.base.AbstractInstant.isAfter(org.joda.time.ReadableInstant) on instance: 2016-11-24T09:20:46
var DateTime dtHeizungsanlage = parse(HzgAnlage_DateString.state + "T" + HzgAnlage_TimeString.state)
val dtAktuell = new DateTime((Datum.state as DateTimeType).calendar.timeInMillis)
var boolean bSyncroInaktiv = dtAktuell.isAfter(dtHeizungsanlage.plusSeconds(180))
I don’t know why I have to create first a new DateTime object with “dtAktuell” because “Datum” is already a DateTime item (defined in the *.items file) and transform it to milliseconds to work correctly. For me it seems to work with date and time objects in rules is a pain in my ass.
Unfortunately the DateTime Item is of type DateTimeItem, and this Item’s state is of type DateTimeType. But DateTime is of type org.joda.datetime.DateTime (or something like that). So, in short, a DateTimeType is completely different from a DateTime which is why you have to do this round about conversion.
It is indeed a pain but I’m certain there is some insurmountable reason why they cannot make DateTimeType be a Joda DateTime.
It would be nice to make DateTimeType smarter and more capable, but I think it was not done previously so as to not be dependent on a third-party library. Java 8’s java.time package could help (see here and examples here), but only after Eclipse SmartHome moves to a minimum of Java 8.
and what i get back is a string with the format “2017-02-16 06:05:00” - How can i extract the Date from this string or even better, can i create a DateTime variable from it?
i found a solution myself, am not sure if this is the best way, but i think i can deal with it:
var Number alarmTimeHour = 0
var Number alarmTimeMinute = 0
var Number alarmDateDay = 0
rule "Sonos Wecker Integration"
when
Item sonos_alarm_raw received update
then
var AlarmDateTime = sonos_alarm_raw.state.toString().split(" ")
var AlarmDate = AlarmDateTime.get(0).toString().split("-")
var AlarmTime = AlarmDateTime.get(1).toString().split(":")
alarmTimeHour = Integer::parseInt(AlarmTime.get(0))
alarmTimeMinute = Integer::parseInt(AlarmTime.get(1))
alarmDateDay = Integer::parseInt(AlarmDate.get(2))
end
Sorry for not answering before – missed it until now! In the string above, you could have replaced the " " with a “T” and then it would have become an acceptable string from which to construct a new DateTimeType(xxx).
See the code here for the formats accepted when creating a DateTimeType.