Sorting DateTime value's from Calendar Events

Hello,

I’m using iCalendar to retrieve events from two different calendars.
I placed 5 upcoming events from both calendars into Items, so got a total of 10.
The only problem is they are not yet in order of upcoming events, so I would like to sort them based on the DateTime value.

After 2 days trying and searching, I haven’t found a solution, so maybe there isn’t an easy solution.

I have tried to place the Items into a Item Group en use SortBy[state] to sort them, but this doesn’t seem te work.
I got an error:

failed: class org.openhab.core.library.types.DateTimeType cannot be cast to class java.lang.Comparable (org.openhab.core.library.types.DateTimeType is in unnamed module of loader org.eclipse.osgi.internal.loader.EquinoxClassLoader @1934694; java.lang.Comparable is in module java.base of loader 'bootstrap')

But other options like state by DateTimeType or other options are giving error or still an unsorted result.

Is it possible in some way to sort this based on order which event comes first?

I hope it’s clear what I want to achieve.

Regards,
Edwin

Where are you trying to do this sorting? In a rule? Sitemap? MainUI widget?

Sorry, didn’t mention, but in Rules.

Language? There are half a dozen different rules languages supported by OH right now.

To be honest I have no idea, but guess it’s Java since that the standard now if I’m understand correctly.

I have trying to write my own sorting script, but again got the problem that the command isn’t available for comparing two date’s.
In this case I wanted to use isBefore () for comparison.

I have the following:
Two different DateTime variables, with a value like the following: 2022-02-06T08:00:00.000+0100
To create a sorting script I need two know if date1 is before date2.
I found al lot of different options to use, but the all give an error that the command isn’t a member of org.openhab.core.library.types.DateTimeType

I feel lost in all the different methodes and probably mixing them around.

Quite possibly. Step one, let’s find out what you’re working with. Posting the rule in question would give us a start. If you’re using the GUI rule entry, show us what the ‘code’ tab shows you. If you’re editing files, what files?

Definitely post what you’ve done and the error logs you are seeing. We are kind of flying blind here so it’s hard to help. And since Java is not the standard rules language we still don’t know some key pieces of information that seeing the code will let us immediately see.

I’ve got the following to start and test:

rule "Calendar Sorting"
when
	Member of gAgendaAfspraken changed
then
	val DateTimeType date1 = calendar_event1_start.state
	val DateTimeType date2 = calendar_event2_start.state

	logInfo("Calendar rule", "date1: "+ date1.toString() )
	logInfo("Calendar rule", "date2: "+ date2.toString() )

	if ( date1.isBefore(date2) ) {
		logInfo("Calendar", "Date1 is before date2")
	}

end

The logging is giving me the following:

2022-02-01 16:38:32.454 [INFO ] [nhab.core.model.script.Calendar rule] - date1: 2022-02-05T14:00:00.000+0100
2022-02-01 16:38:32.457 [INFO ] [nhab.core.model.script.Calendar rule] - date2: 2022-02-11T08:00:00.000+0100
2022-02-01 16:38:32.458 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'agenda-2' failed: 'isBefore' is not a member of 'org.openhab.core.library.types.DateTimeType'; line 167, column 7, length 21 in agenda

OK, just for clarity, that’s a Rules DSL rule (a language specific to openHAB) written in a text file.

So, an Item holds a state. A DateTime Item holds a DateTimeType as its state. But a DateTimeType itself holds the actual DateTime (a ZonedDateTime to be precise). So before you can do DateTime stuff to it, you have to extract the ZonedDateTime.

So, before you can call isBefore() or isAfter()you can change:

	val date1 = calendar_event1_start.state.getZonedDateTime()
	val date2 = calendar_event2_start.state.getZonedDateTime()

Notice there are two changes: 1. don’t define the type unless you have to in Rules DSL, and besides that was the wrong type now that we are pulling the ZonedDateTime; 2. we are getting the ZonedDateTime from the state.

There is a chance that won’t work though. Sometimes Rules DSL is brilliant about figuring out type, and in other cases it’s quite dumb. If this is the latter case:

	val date1 = (calendar_event1_start.state as DateTimeType).getZonedDateTime()
	val date2 = (calendar_event2_start.state as DateTimeType).getZonedDateTime()

That tells the engine that we want to use the state as a DateTimeType. Otherwise it’s treated as a State and State doesn’t have a getZonedDateTime() method.

That should make the rule above work. But this is sort of an XY problem.

But you’ve got a whole Group of DateTime Items and presumably you want to sort them all. We can do that with a sortBy, but we need to support by the ZonedDateTime (which is a Comparable so sortBy should work).

val sorted = gAgendaAfspraken.members.sortBy[ i | (i.state as DateTimeType).getZonedDateTime() ]

Thank you for you’re explanation.
After reading it a few times I’m starting to understand what the issue is or was.

I’ve got it working now.
The second option was the correct one.

val date1 = (calendar_event1_start.state as DateTimeType).getZonedDateTime()
val date2 = (calendar_event2_start.state as DateTimeType).getZonedDateTime()

With this the SortBy also works.