OH2: Parse String to DateTime Object

All,

(openhabian, raspberry pi 3, OH2.2 stable)

I get a json response which looks like:
2018-06-16T13:12:11+00:00

I other posts I have seen that I could separate each part of it (hour, minute, etc), but I assume that there is a better way like parsing strings to Number items!?

If so, I would appreciate an example how to do it.
Thanks

What do you want to get, a timestamp or a special part of the value e.g. date?

HI Harry,

Sorry I was unprecise.
I would like to get A DateTime Object and format it to
dd.MM.yy - H:mm

What binding are you using?

Use the JSONPATH transform to get your value into a DateTime item
Format the item as follow:

DateTime myItem “[%1$td.%1$tm.%1$ty - %1$tH:%1$tM]” { your binding with JSONPATH }

I actualyy get the JSON response on my request which looks like:
val String time = transform(“JSONPATH”, “$.trips[0].tripDetails[0].startTime”, json)

I would like to parse this to a DateTime item like
CarTripStart.postUpdate(time)

What type is $.trips[0].tripDetails[0].startTime?
If it is DateTime, I would’t convert to string, but store the value as DateTime.

It should work

That looks like a standard ISO 8601 date time string.

I think there is a constructor on Joda DateTime that will take the string and parse it for you. I know you can send this string unchanged as an update to a DateTime Item as is. I also suspect there is a constructor on DateTimeType that will take this string and parse it for you.

I will try.
I hope it’s really that easy.
Sometimes I think a little too complicated…
:wink:

Did you figure this out yet? I am parsing the String that’s output by the NTP binding, which looks like:

2018-06-19T10:50:15.976-0500

by using the following code:

var DateTime Local_JDT = parse(Local_DateTimeStr.state.toString)    // Get Local JDT     

where Local_DateTimeStr is the string output from the NTP binding. It’s ISO 8601 with timezone. Which yours is as well, like Rich said. The documentation for the parse function is here: http://joda-time.sourceforge.net/apidocs/org/joda/time/DateTime.html#parse(java.lang.String)

you should be able to simply do the following in your rule:

val String time = transform(“JSONPATH”, “$.trips[0].tripDetails[0].startTime”, json) // Your original rule code
var DateTime JDT_time = parse(time.toString)    // Parse JDT object from timestring
var DateTimeType DTT_time = new DateTimeType(JDT_time.toString)   // Convert JodaDateTime to DateTimeType 
CarTripStart.postUpdate(DTT_time)         // This should now work without ".toString"

Please let me know if this works! I’m new to this, but want to start helping out. If that doesn’t work you may need to specify the format using parse(string, DateTimeFormatter formatter), which I’ve done but would have to brush up on.

Phil

1 Like

Thanks, Phil.
I thought I did it by the following (simplest) approach, but I just get the following DateTime result:
2018-06-16 00:00:00.000 (so no time, just date)

val String time = transform("JSONPATH", "$.trips[0].tripDetails[0].startTime", json)
CarTripStart.postUpdate(time) // whereas CarTripStart is DateTime type

In the log it looks good, though:
time: >2018-06-19T17:25:13+00:00<

However, I will try your suggestion and let you know.
Thanks for your help!

This fails:
Rule 'Request Last trip Details': java.lang.Integer cannot be cast to java.lang.String

val String dist leads in the log to:
2018-06-20T07:34:39+00:00

var DateTime timeDT = parse(time.toString) leads in the log to
2018-06-20T07:34:39.000Z

postUpdate on a DateTime item does obviously lead to the error above:
CarTripStart.postUpdate(timeDT)

Shouldn’t "toString be something like StringtoDateTime or similar?

OK, so unfortunately you cannot send a Joda DateTime Object as a command to a DateTime Item. It must be either a DateTimeType Object or a String. So try:

CarTripStart.postUpdate(timeDT.toString)

Thanks, Rich - I will check it out.

After reading Rich’s last post I starting thinking I had forgot a line and I did! I added it above in my original post, but you need to convert JodaDateTime to DateTimeType:

var DateTimeType DTT_time = new DateTimeType(JDT_time.toString)   // Convert JodaDateTime to DateTimeType 

The code in my original post should work, but please check the variables, etc. It is very frustrating working with time types in these rules, I will admit.

Phil

Thanks Phil.
I will try your modification as soon as I have another window of opportunity :slight_smile:

Hi Phil,

it seems to work.
But I get an error during startup:
The method getCalendar() from the type DateTimeType is deprecated

And I get (during startup):

2018-06-27 21:02:06.929 [ERROR] [g.eclipse.smarthome.core.persistence] - [org.eclipse.smarthome.core.persistence.internal.PersistenceManagerImpl(75)] The addPersistenceService method has thrown an exception
java.lang.ClassCastException: java.lang.String cannot be cast to java.sql.Timestamp

I guess this is related to my case above?!

I’m not totally sure but I wonder if those issues aren’t caused by another rule somewhere. I actually went through quite a bit of effort to figure out the appropriate syntax to avoid the “The method getCalendar() from the type DateTimeType is deprecated” Error. And, my rule example never uses the getCalendar() method. I am running OpenHAB2.3.0 Release Build, and I just tested the following and it works with no errors. Since I do not know what binding, etc. is providing your JSON string time response, I just make a static val equal to your original time string from the top post in this thread, and commented out the line of code that gets your string from a JSON response. The following should work exactly as written:

Here are the applicable items in an items file:

// Testing Group and Variables
Group       Test            "Testing/Debug"              
Switch      TestSwitch      "Test Switch [%s]"                      (Test)
DateTime    TestTime        "Test Time [%1$tH:%1$tM:%1$tS, %1$tm/%1$td/%1$tY]" <clock> (Test)

Here is the applicable rule in the rules file:

// ------------------- RULE ------------------- 
rule "Test Switch Changed"
when
    Item TestSwitch received command
then
    logInfo("TEST","RULE FIRED: Test Switch Changed")

    // --- Test code for DateTime Parse functionality ---
    if (TestSwitch.state == OFF) {TestTime.postUpdate(NULL)}
    else {
        val String time = "2018-06-16T13:12:11+00:00"   // Original post time string
        //val String time = transform(“JSONPATH”, “$.trips[0].tripDetails[0].startTime”, json) // Your original rule code
        var DateTime JDT_time = parse(time.toString)    // Parse JDT object from timestring
        var DateTimeType DTT_time = new DateTimeType(JDT_time.toString)   // Convert JodaDateTime to DateTimeType 
        TestTime.postUpdate(DTT_time)                   // CarTripStart item changed to TestTime for the purpose of this test
    }
    // ----------------------------------------

end

Then, add the TestSwitch to sitemap. I have a “Test” group and “TestSwitch” item permanently, as well as the “TestSwitch” on my sitemap and a “test.rules” file so that I can always test things quickly and easily, without possibly damaging another set of code.

When you activate the TestSwitch on the sitemap (to ON) you should see the following (turning it off returns the timestamp to NULL:

18:28:56.803 [INFO ] [smarthome.event.ItemStateChangedEvent] - TestTime changed from NULL to 2018-06-16T13:12:11.000+0000

Let us know if this works. If it does, try to apply this code as closely as possible to your specific case.

Phil

Hi Phil,

I really appreciate your endurance in supporting me in my case.
Actually I have a permanent Debug_Trigger switch for such kind of investigations.
I will try your code and let you know.

Maybe you are right, that it comes from another rule.
By the way, the json response comes from the volvo on call python stuff