DateTime Conversion (openHAB 2.x)

I believe he was referring to the updates sent by Habdroid for the alarm clock, but I could be wrong!

This is what I was thinking of…

Oh, wait… there’s this too!

1 Like

That’s an awesome HowTo!
I always struggle with the time formats.
This helps a lot in this Jungle!
Thanks a mil!

Hi
I’m just checking before I go down this rabbit hole of wonders…

Is your Phone_AlarmClock item getting updates from the Android openHAB2 app, that in turn gets updates from the Android alarm clock feature… ???

Sorry to disturb you.

May I pick your brains?

I’m trying to separate just the hour and minute from a dateTime Item.

Would something like this work?

var Hour = new DateTime((Phone_AlarmClock.state as Number).hour)
var Min = new DateTime((Phone_AlarmClock.state as Number).minute)

I haven’t been able to get my head around how to handle DateTime Type

Update

I’m not entirely sure why, but this seems to be doing the trick

   rule "Stu phone alarm time"
 when
 Item Stu_AlarmClock changed
 then


 val DateTime TodayJoda = now
 val TodayDoY = TodayJoda.toString("D")

 val DateTime myJoda = new DateTime(triggeringItem.state.toString)
 var DoY = myJoda.toString("D")
 var Hour = myJoda.toString("k")
 var Min = myJoda.toString("m")

 logInfo("test","Today is DoY = "+TodayDoY+" Alarm Day of Year = "+DoY+" Hour = "+Hour+" & Minute = "+Min)
 TestHour.sendCommand(Hour)
 TestMinute.sendCommand(Min)

 end

There’s some more to do with this to get to where I want, but I think I’m in the right direction now

Its like the evolution of man

Its taken an hour or so, but I think this is what I was hoping for

  rule "Stu phone alarm time"
 when
 Item Stu_AlarmClock changed
 or
 System started
 or
Time cron "0 10 0 1/1 * ? *"

 then


 val Number AlarmEpoch = (Stu_AlarmClock.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli

 val DateTime TodayJoda = now
 val TodayDoY = TodayJoda.toString("D")

 val DateTime myJoda = new DateTime(Stu_AlarmClock.state.toString)
 var DoY = myJoda.toString("D")
 var Hour = myJoda.toString("k")
 var Min = myJoda.toString("m")

 logInfo("test","Today is DoY = "+TodayDoY+" Alarm Day of Year = "+DoY+" Hour = "+Hour+" & Minute = "+Min)


 logInfo("test"," Alarm Epoch = "+AlarmEpoch)

 if (AlarmEpoch >=0){ if ( DoY == TodayDoY ){
 logInfo("test","Conditions True")





 TestHour.sendCommand(Hour)
 TestMinute.sendCommand(Min)
         // SwitchAlarm.sendCommamd(ON)
         logInfo("test","Switch Alarm ON")
 return
         }        }
 TestHour.sendCommand(0)
 TestMinute.sendCommand(0)
 logInfo("test","Switch alarm OFF")
 // SwitchAlarm.sendCommamd(OFF)

 end

im hoping it can help

A great resource for understanding this better is the awesome time conversion thread by rud @anfaenger found here here

1 Like

What part are you unsure about? The code

  • Gets the current time as a Joda DateTime (TodayJoda)
  • Converts the DateTimeType from Stu_AlarmClock to a Joda DateTime (myJoda)
  • Extracts the day (DoY), hour, and minute as a String
  • Sends the hour to TestHour and minute to TestMinute as commands

To get those values as numbers instead of Strings

val DoY = myJoda.dayOfYear
val Hour = myJoda.hourOfDay
val Min = myJoda.minuteOfHour

I’m going from memory, the calls might be a little different. Use VSCode and it should show you the right ones.

1 Like

Hi All

I am trying to manipulate some Date and Time Items to be able to hide Frames in a sitemap using the “visibility” options.

I have the recorded the time an item last updated as a string using the following rule:

rule "Partition 1 Alarm Timestamp"
when
    Item Partition1_AlarmMemory changed to ON or
    Item Testing_Switch received command ON
then
        postUpdate(Partition1_Last_Alarm, new DateTimeType())
        logInfo("", "Partition 1 Alarm Timestamp " + Partition1_Last_Alarm.state )
end

Partion1_Last_Alarm is a STRING item defined in PaperUI.

I also have the current time defined by the following rule:

rule SetDay
when
    System started or
    Item Testing_Switch received command ON or
    Time is midnight
then
    Today.postUpdate(new DateTimeType())
end

Which I display using the sitemap as follows (so no formatting):

    Default item=Today                      label="Today [%s]" 
    Default item=Partition1_Last_Alarm		label="Today [%s]"  

And I get the following outputs:

Today			        2020-10-16T11:30:22.961+02:00
Partition1_Last_Alarm	2020-10-16T11:09:03.010+02:00

From what I have read these are ISO8601 format? And I would like to convert them to be Number Values (Epoch) so that I can compare and make decisions in the visibility statements. (E.g. visibility=[Partition1_Last_Alarm > Today]

So I have used the following to try and convert to EPOCH based on DateTime Conversion #9

rule SetDay
when
    System started or
    Item Testing_Switch received command ON or
    Time is midnight
then
    Today.postUpdate(new DateTimeType())
//Removed.millis as end of next as seconds OK
    val Number Today_Epoch_Val = new DateTime(Today)
    Today_Epoch.postUpdate(new DateTimeType())   
end

I however get the following error in the logs and no matter what I have tried I still get the error:

14:52:32.417 [INFO ] [smarthome.event.ItemStateChangedEvent] - Today changed from 2020-10-16T11:30:22.961+0200 to 2020-10-16T14:52:32.417+0200
14:52:32.417 [ERROR] [untime.internal.engine.RuleEngineImpl] - Error during the execution of startup rule 'SetDay': No instant converter found for type: org.eclipse.smarthome.core.library.items.StringItem
14:52:32.417 [INFO ] [org.quartz.core.QuartzScheduler      ] - Scheduler openHAB-job-scheduler_$_NON_CLUSTERED started.

Today_Epoch is an item defined in PaperUI as a Number with no dimension applied at this stage.

I expect that if I can get Today to work the same would apply for the Partition1_Last_Alarm item as well.

Any hints or guidance would be greatly appreciated.

Mark

There is a lot of confusion in that short little rule.

Today is an Item, not a DateTime. You can’t create a DateTime using an Item. You have to use either epoch or an ISO8601 formatted String.

Removing .millis doesn’t round epoch to the nearest second. .millis literally returns the epoch. By removing that you are not longer dealing with epoch.

To store the epoch value so you can use it in your visibility on the sitemap, Today_Epoch needs to be a Number Item. You can’t update a Number Item with a DateTimeType. Conversely, if it isn’t a Number Item than the Item can’t store epoch.

To put epoch for today at midnight (which is what you really need I think) into a Number Item Today_Epoch all you need is

    val midnight_today = now.withTimeAtStartOfDay()
    Today.postUpdate(midnight_today)
    Today_Epoch.postUpdate(midnight_today.millis)

Hi @rlkoshak Thanks for the clarification.

Yes, I do need a midnight time as one element, and would still need to convert the String from Partition1_AlarmMemory to EPOCH as well in order to use both in the visibility?
I am really new to coding at this level, so plenty of confusion.

I have changed rule to:

rule SetDay
when
    System started or
    Item Testing_Switch received command ON or
    Time is midnight
then
    val midnight_today = now.withTimeAtStartOfDay()

    Today.postUpdate(midnight_today)

    Today_Epoch.postUpdate(midnight_today.millis)  
end 

I now get the following error:

18:59:31.566 [INFO ] [del.core.internal.ModelRepositoryImpl] - Refreshing model 'time.rules'
18:59:36.635 [ERROR] [untime.internal.engine.RuleEngineImpl] - Error during the execution of startup rule 'SetDay': Could not invoke method: org.eclipse.smarthome.model.script.actions.BusEvent.postUpdate(org.eclipse.smarthome.core.items.Item,java.lang.String) on instance: null

Any ideas why that would be? And what I need to do to convert the STRING from the item that already exists?

Thanks
Mark

EDIT: Updated to:

Today.postUpdate(midnight_today.**toString**)

And works Thanks

Today_Epoch is a Number Item?

    val alarm_epoch = new DateTime(Partition1_AlarmMemory.state.toString).millis
    Partition1_AlarmMemory_Epoch.postUpdate(alarm_epoch) // you need to create this Item

What String from what item that already exists?

@rlkoshak
Yes, I have checked and Today_Epoch is a Number Item - with no dimension
Will try the code snip above as soon as I can get the error cleared from the Midnight_Today piece.

Partition1_AlarmMemory is a a channel from my Caddx binding. When this changes I log the Time to the Partition1_Last_Alarm String item (I think I was unclear in my reply above):

rule "Partition 1 Alarm Timestamp"
when
    Item Partition1_AlarmMemory changed to ON or
    Item Testing_Switch received command ON
then
        postUpdate(Partition1_Last_Alarm, new DateTimeType())
        logInfo("", "Partition 1 Alarm Timestamp " + Partition1_Last_Alarm.state )
end

I will be using the two items Today_Epoch and Partition1_AlarmMemory_Epoch in my visibilty condition.

EDIT: Tested the Partiton1_AlarmMemory_Epoch snippit - works great! Thanks

Mark

You don’t need a Rule for this. See the timestamp profiles. Items | openHAB

Note that this should be a DateTime Item, not a String Item.

@rlkoshak
Great, thank you. Will take a detailed look. At first glance though this would timestamp each change (On and Off). I am only interested in On.

With your help though I now seem to have the two epoch items I need. So will see how far I get from here.

Working with DateTime is clearly way more complex that I expected.

You’re spending a lot of time on rules, but if the above is the purpose … what did you have in mind?
You cannot set set visibility along the lines of “if it is after six pm”.

I have now realized that you cannot compare two items in visibility - which presents a small challenge, but will work though that. Will just use the Epoch value to get an age of the information I want/don’t want to display.
The alarm system I am using sets flags for the zones which generated the last alarm. These do not update until they are cleared by the next alarm event, so once they are a certain age they become irrelevant, so want to hide them from view.

So thinking along the lines of only displaying the relevant groups of zones if the last alarm was within the last 24 hours (maybe allow a variable time period: 1 day, 2 days, 7 days).
That way there is only an option to see recent Zones which caused alarms on a Partition (Area) that has had an alarm in X time.

Hope I have explained clearly enough.

Always open to better more streamlined approaches though. Hoping to post my project to the Caddx Binding section as a sample at some stage when I have completed the basics.
Thanks again.

Think I’d use a dummy Item, maybe a switch. When update comes in, set switch on. Apply expire binding to switch off, if using fixed delay. If you want a variable delay, use a rules based timer. All this is just a variation of motion activated light.
Then sitemap visibility is simply about the switch on or off.

EDIT - following a different track

Alright, so to put it another way, you have captured alarm events in your static Item states. And you’d like them to go away after a time.
This is classic expire binding job, just apply expire to each Item.

Thank you for the great suggestion. That would be exactly what I wanted… Should have found this earlier - but know for future. The “problem” is the more you do, the more you want to try.

In his OH3 announcement, Kai said

The only change you’ll have to look our for in your rules is the fact that rules now use Java Time API instead of Jodatime, so some expressions need to be slightly adapted.

Could anyone explain what that means to the information in this thread ?
What do we need to change in our working rules ?
How much of Joda will there be left to be used in rules ?

1 Like

Before we change something.
Would it make sense to copy the content of this thread into a new one called DateTimeConversion (openHAB 3.x)?
I would then rename this original thread to DateTimeConversion (openHAB 2.x).
This would not lose any information for users who do not immediately switch to 3.x.

2 Likes

Yes rename it and open a new 3.X thread and link the two.
But only copy what’s relevant (and confirmed to work) to OH3. As of today that’s not clear at least to me it is not.

I’m particularly worried about replacing now, XXX.withTimeAtStartOfDay, XXX.plusMinutes(n) and so on and I think others will be interested, too.