Parse String to DateTime object

Hi all,

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'.

What is the wrong with this statement?

You need to import org.joda.datetime.*

I’ve added this import but OH Designer 1.8.3 still throws this errors:

- Couldn't resolve reference to JvmIdentifiableElement 'DateTime'.
- Couldn't resolve reference to JvmType '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:

dtAktuell.isAfter(dtHeizungsanlage.plusSeconds(120)
[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

What is working now is the following code:

    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.

i have a similar approach and don’t want to create a new topic for that:

i want to integrate the sonos alarm clock to my heating rules and need to know the evening before if there is an upcoming alarm or not.

I got the data i needed via xsl transformation:

String		sonos_alarm_raw				"Wecker Uhrzeit [%s]" 								{ http="<[http://yourSonosIP:1400/status/alarm:300000:XSLT(alarm.xsl)]" }

with alarm.xsl:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml" encoding="UTF-8" omit-xml-declaration="yes" />

<xsl:template match="/">
		<xsl:value-of select="ZPSupportInfo/Alarm/Pending/PendingAlarm/NextLocal" />
</xsl:template>
</xsl:stylesheet>

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?

Thanks!

No one? What about the experts @watou or @rlkoshak?
Can i just get character xy to store in a number?

1 Like

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

Thanks anyway!

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.

Thanks for your reply, i will try which advantages i have with a “correct” DateTimeType in comparison with my “dirty” solution :wink: