How to extract hour and min from DateTime

I have setup an Item explained in here. Next step is to write the time to one of my Modbus devices. Hour of the DateTime Item goes to Modbus register 2011 and Min goes to register 4011. I know how to write to these registers but my problem is how to extract Hour and Min values from the DateTime Item in a DSL rule. I have spent already few hours with googling but haven’t found an example which would tell how to do this.

I’m also wondering one thing. The time input is in 12-hour format as in the link (post #2) on my PC (with Chrome and FF) but on my Android phone the same Item has 24-hour format.

If you look in threads like this, there should some example of extraction. Moreover it will give you info on the different representations of time. The methodIcould be item.hour() or something similar. The problem is to convert the information in the right format so that it can be accepted by the item you want to set

Thanks. Unfortunately I haven’t figured out a solution to this trivial problem. I found in one post using .toHours method but it doesn’t work.

Latest version of my DSL script looks like this:

Var Hour = Etuvalot_Off.toHours.toString
Var Min = Etuvalot_Off.toMinutesPart.toString
logInfo("Etuvalot_Off", Etuvalot_Off.state.toString)
logInfo("Etuvalot_Off hour", Hour.state.toString)  
logInfo("Etuvalot_Off min", Min.state.toString)    
 
OHJ_Reg4.sendCommand(256)
OHJ_Reg2011.sendCommand(Hour)
OHJ_Reg4011.sendCommand(Min)

In the log I have errors:

2022-01-15 11:45:02.338 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'f35a36154a' failed:  ___ Var  ___ Hour = Etuvalot_Off. ___ toHours.toString
Var Min = Etuvalot_Off.toMinutesPart.toSt ___ ring ___ 
logInfo("Etuvalot_Off", Etuvalot_Off.state.toString)
logInfo("Etuvalot_Off hour", Hour.state.toString)  
logInfo("Etuvalot_Off min", Min.state.toString)    
 
OHJ_Reg4.sendCommand(256)
OHJ_Reg2011.sendCommand(Hour)
OHJ_Reg4011.sendCommand(Min)


   1. The method or field Var is undefined; line 1, column 0, length 3
   2. The method Hour(Object) is undefined; line 1, column 4, length 4
   3. The method or field toHours is undefined for the type DateTimeItem; line 1, column 24, length 7
   4. The method or field Var is undefined; line 2, column 41, length 3
   5. The method Min(Object) is undefined; line 2, column 45, length 3
   6. The method or field toMinutesPart is undefined for the type DateTimeItem; line 2, column 64, length 13
   7. The method or field Hour is undefined; line 4, column 169, length 4
   8. The method or field Min is undefined; line 5, column 220, length 3
   9. The method or field Hour is undefined; line 8, column 296, length 4
   10. The method or field Min is undefined; line 9, column 326, length 3

So obviously the method I have used is wrong.

Item Etuvalot_Off is a string:

1970-01-01T19:30:00.000+0200

So Hour should be 19 and Min 30.

I’m still runnning Homeseer and in VB scripting this issue is really trivial.

This is ambiguous. Is it an Item, or a string variable? Very different things.

Guessing it is an Item, it is the state that you are interested in - not other Item properties like label or icon.

Guessing it is an Item of type String, its state will be a collection of characters. That might look like some date or time to you, but the machine can’t treat it as a datetime unless you first parse the character string into a datetime type variable.

What language are you scripting in? It looks like you might be trying to use DSL, but have told the GUI rule script it is javascript?

Sorry, I’m so confused about everything right now. Etuvalot_Off is an Item and I have defined it as a DateTime. I don’t know anything about javascript yet so I’m trying to use DSL but the syntax I have used is obviously completely wrong.

So, basically I want to extract hour and min e.g. from a string:

1970-01-01T19:30:00.000+0200
1 Like

Alright.
Datetimes in general are a complex topic, you should probably review -

Don’t approach this as a trivial job at all.

Take it on trust that it is almost always best to get a DateTime Item state into a rule as a ZonedDateTime type java object, because the ZDT comes with a lot of useful methods.

logInfo("test" , "Etuvalot state " + Etuvalot_Off.state.toString)

// get OH Item state as ZDT object
val EtuvalotZDT = (Etuvalot_Off.state as DateTimeType).getZonedDateTime

// get parts
val evHour = EtuvalotZDT.getHour
logInfo("test" , "Etuvalot hour " + evHour.toString)

Be sure to tell the GUI what script language you are using.

1 Like

Great, many thanks. Your test script extracts the hour correctly. I guess it will be relatively straightforward now to extract the mins and then write them to MB registers.

I wish there was a tutorial for DSL somewhere but I guess there isn’t. I found this post (#3).

I also had a look at the DateTime Conversion tutorial but didn’t understand it. I need to have a look again.

The time library from Date and Time that is available for blockly is able to extract the hour and minutes from a date time:

I have now managed to create my rule and script.

// get OH Item state as ZDT object
val EtuvalotZDT = (Etuvalot_Off.state as DateTimeType).getZonedDateTime

// get parts
val evHour = EtuvalotZDT.getHour
val evMin = EtuvalotZDT.getMinute
 
OHJ_Reg4.sendCommand(256)
Thread::sleep(300)
OHJ_Reg2011.sendCommand(evHour)
OHJ_Reg4011.sendCommand(evMin)

This script writes first 256 to MB reg 4 and when running the script for the first time 2nd command didn’t update the MB reg 2011. I added a short delay using Thread::sleep but I have read from somewhere that this is not the best way of creating delay (or timer). So, what is the best way to create a short delay or timer?

One thing which I also wonder is that the time seems to have 12-hour format when typing the time in the GUI card but underneath the Item (Etuvalot Off aika) the time is in 24-hour format (see attached photo).

.

Code for the widget:

value: oh-input-item
config:
  clearButton: true
  defaultValue: 
  footer: =items.Etuvalot_Off.state
  inputmode: text
  outline: true
  placeholder: hh:mm
  sendButton: true
  type: time
  validate: true

The time in my Android also has 24-hour format. This is really confusing and somewhat annoying.

Many thanks. As I’m very new to OH how do you use this?

For less than a second, and particularly as I doubt you are running this very often, it’s fine.

The timing requirement here is from your mystery device.

What is the query?

A Datetime type Item holds a datetime value, representing some instant in time. There’s no concept of 12/24 hours, weekday name etc. unitl you extract that instant and format in some way. Likewise, it doesn’t care about format being used for updates - it all ends up as some instant.

Why the MainUI card happens to present as 12 hours and not 24 hours, I don’t know, perhaps this

Often HH:mm represents something different

OK, thanks. Yes, my device is a mystery one. I’m running most of the scripts without any problems but in few cases with a slider card it seems that updating the MB reg lags behind so I have to spend more time with these Items.

With logInfo(“test” , "Etuvalot state " + Etuvalot_Off.state.toString) I get a string in the log file:

1970-01-01T19:30:00.000+0200

so this is in 24 hour format. I took the input card from this post. I’ll have a look at this post again if there is something about the 12/24 hour format.

Assuming you have openhab3.2, you need to copy the code at the end of the first post in that link, in your developer tools / block libraries. Then you can use the new library when you create a new action in a rule and select run a script and then blockly. You will find the added functions under the libraries tab

Great, many thanks for the info.

1 Like

Thanks to everyone involved in this thread.

I searched for a couple of hours and tried some strange methods to achieve something simple.

What I needed to do was extract the Hour and Minutes from a DateTime Item, so that they can be pushed into two separate Items

This rule needs tidying up, but it’s doing exactly what I need.

rule "Split hours and minutes"

when Item textFile_wakeup1 received command   /// The DateTime Item used in the UI

then



logInfo("Split times","New Time = "+receivedCommand)   /// Just to show it is working in the log





// get OH Item state as ZDT object
val weekdayWakeZDT = (receivedCommand as DateTimeType).getZonedDateTime

// get parts
val hours = weekdayWakeZDT.getHour
val minutes = weekdayWakeZDT.getMinute




logInfo("Split times","New Hour = "+hours)
//      Global_Alarm1_WakeHr.sendCommand(hours)


logInfo("Split times","New Minute = "+minutes)
//      Global_Alarm1_WakeMin.sendCommand(minutes)


end