-
-
Notifications
You must be signed in to change notification settings - Fork 431
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add lastStateUpdate
, lastStateChange
to ItemStateUpdatedEvent
/ItemStateChangedEvent
#4606
base: main
Are you sure you want to change the base?
Add lastStateUpdate
, lastStateChange
to ItemStateUpdatedEvent
/ItemStateChangedEvent
#4606
Conversation
42aa018
to
67c4681
Compare
@jimtng just a generic thought: I see that you are using |
I thought about it, but have no preference either way. I chose ZonedDateTime because Item.getLastStateUpdate etc use ZonedDateTime too. WDYT, should we change everything to Instant? ZDT has a lot more useful methods to operate with, so that's a plus for it. |
I think the principle is that OH Core data is independent of the timezone (i.e. using Instant) and that OH UI converts to the local timezone at the point of display. |
67c4681
to
1346a0b
Compare
OK, and considering that DateTimeType also switched to Instant, it would indeed be uniform to make this also Instant. Since the Item.getLastStateUpdate etc was just recently merged, I hope it's ok to change it. |
How would the instant be represented when sending the event over websockets? |
I'd imagine something like this:
It's iso8601 |
@jlaur I think you have done some other work in OH concerning Instant vs ZonedDateTime, so perhaps you have an opinion here? |
PersistenceExtensions still use ZonedDateTime. My modified build just hit a problem there that I need to adjust. |
The change to Instant will affect the recent changes in mapdb that utilise getLastStateUpdate/Change - @mherwege just FYI - atm this is subject to maintainer's review. |
@@ -476,15 +477,21 @@ private static void internalPersist(Item item, TimeSeries timeSeries, @Nullable | |||
if (!forward && !historicItem.getState().equals(state)) { | |||
// Last persisted state value different from current state value, so it must have updated | |||
// since last persist. We do not know when from persistence, so get it from the item. | |||
return item.getLastStateUpdate(); | |||
return Optional.ofNullable(item.getLastStateUpdate()) | |||
.map(instant -> instant.atZone(ZoneId.systemDefault())).orElse(null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The class already has a reference to TimeZoneProvider
, so I think the converion should be done using the configured timezone.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
I don't have a problem changing that. I still uses |
e4a69cf
to
e68bd33
Compare
…ItemStateChangedEvent` Signed-off-by: Jimmy Tanagra <[email protected]>
Signed-off-by: Jimmy Tanagra <[email protected]>
Signed-off-by: Jimmy Tanagra <[email protected]>
Signed-off-by: Jimmy Tanagra <[email protected]>
@andrewfg I'm a bit on the fence about Instant vs ZonedDateTime. I'm leaning towards ZonedDateTime for lastStateUpdate/lastStateChange. Both zdt and Instant represent a moment in time, but a ZDT is far more useful in practical usage, in scripts/rules. Both can be used to check "how long ago did it happen", i.e. delta time, but only ZDT gives you the extra information about whether it occurred "today", before noon, etc. which can be useful for writing automation rules. Another benefit for using ZDT is when I log the information, it is immediately displayed in the timezone that I'm familiar with (i.e. my local timezone) instead of Zulu, which requires further mental math to be understood. Of course you can deduce the same information from an Instant but that would require a conversion to ZDT first. And this is a bit inconvenient. So perhaps the question is: where are these going to be used? If they'll be used primarily in rules, ZDT would be more convenient. If they'll be used primarily in UI, perhaps Instant offers better flexibility in the same manner that DateTimeType, i.e. an item's state, is handled. |
e68bd33
to
0950471
Compare
Signed-off-by: Jimmy Tanagra <[email protected]>
0950471
to
0a1e582
Compare
No doubt you can do more, when you also have the time-zone. The question is, which time-zone? If you store the time-zone at the moment of the event, it could change afterwards. Many bindings went through a lot effort to obtain the time-zone from Since it's easy to create a For reference (especially the first mentioned issue might be worth a read):
You could still convert to
|
Signed-off-by: Jimmy Tanagra <[email protected]>
OK, then we'll use Instant for this.
In the case of DateTimeType, it was done in its |
You are right it's a trick, it's even a cheap trick since it uses the system time-zone and not the configured time-zone in OH. It's more or less left for backwards compatibility as an
Can you provide me with a reference to where this happens in the code? I could have a look, but you are probably right it's not so easy to fix, especially if it's not possible to obtain an injected |
It's not an issue of getting a TimeZoneProvider.
Contrast this to DateTimeType object. When one wishes to log this DateTimeType object, DateTimeType.toString() is called. Hence why I said, we can create a wrapper for Instant and ItemStateChangedEvent.getLastStateChange() can return an object of that wrapper, but I don't like that solution. It's not a huge deal, and maybe I'd just leave it as it is now. |
But at least for Rules DSL users it made getting and interacting with DateTimeType worse, and dealing with date times already sucks in Ruels DSL. I originally asked on that original issue/PR if this would that would be user facing and was told not only to have it show up as a breaking change. I would have spoken up more if I knew users would have to manually add back the tiemzone in all their rules. While I dislike Rules DSL already, I don't want to be hostile to its users. But since these are for the events, how would these be exposed to the Rules DSL user? Presumably, injected as an implicit variable? Maybe there is a chance to do something there. I'm not as worried about the JSR223 languages because they have a helper library to put the timezone back on since pretty much all the time a user in a rule is going to want LocalTime or LocalDateTime and for that you need a timezone. |
Do you have a proposal for how to improve Rules DSL in this regard?
I'm not sure what you are referring to here, or mean, but there are no comments from you in #2898 or #3583. The issue was created in April 2022 and I only managed to get the PR ready around November 2024, so I was not rushing or deliberately ignoring any inputs received in those years. 🙂 As mentioned here I did not anticipate beforehand that Rules DSL would be affected. However, the effect is (currently) minimized to 1) using system time-zone rather than |
Not make them have to supply the tiemzone every time they want to work with their local time.
Then I must be remembering a different issue that UI'm confusing with those. There was some issue or PR that dealt with replacing ZDT with Instant that I commented on. I must be confusing them.
This is the part that is a worse experience for Rules DSL users. Almost all the time a user wants to work in local time, not zulu. This means that almost all the time they have to manually add the timezone in order to get to local time. We've gone from needing to supply the timezone being the exception to needing to supply the timezone being the rule. It's relevant to this issue if these date times are going to be exposed in rules too. Clearly they will be a part of the It's unclear whether/how they will be made available in Rules DSL. I can't imagine their not being made available there. If they are exposed as Instants there too, that means there are even more places where the users have to supply their timezone by default instead of the default being to have the default set for them. Or having to call So to see if
There are more. But if
It still sucks but at least it's no worse and there isn't the extra set of conversions required to and/or from Instant. |
Yes, these will be available as implicit variables
This is indeed the main reason why I'm favouring ZonedDateTime over Instant. Unfortunately, injecting All should be of the same type, either Instant or ZDT. As I understand it, the main reasons for using Instant are:
I'd say for (1) above, it's an extremely rare event and I'd be happy to ignore this "problem". Besides, if one wishes to avoid this issue, they could still call |
This might be way bigger and have more impact than we might want to consider, but what if there were a wrapper Class or something that gave you options. If the end user wants a ZDT they call It can store the actual timestamp as an Instant and if any of the timezone needing getters are called then the system default timezone can be assumed. It's still not as good as everything already being the same type to begin with, but it frees the Rules DSL user from the added burden of keeping track of and manually needing to convert between types. They can just ask for what type they want to use. This is the model that JS uses for State and it seems to work well. If you want the state as a Number, call But for consistency this would almost have to be applied everywhere which could be too big of a job. Maybe we can just do this for rules somehow? That's where the user facing impacts will appear. |
Which part, 1 or 2? Unless you are using someone else's server in another time-zone, the system time-zone should usually be the same as the openHAB time-zone. They can be different, hence the deprecation notice. To continue this particular part of the discussion, I would propose to create an issue for that.
In general, both For
That would reintroduce inconsistency, since then all bindings would then have to provide proper ZDT's rather than Instants. If they don't, we'll have a ZDT with wrong time-zone, which would be exposed in some places, but not in others (when It seems that the main concern and biggest problem in this discussion is Rules DSL, is this correct? The tight coupling between DSL and the type classes seems to be hurting us here, and I would really hope we could find a solution for that rather than let DSL dictate our design. 😢 At least I think we need to be very clear about when we "prefer" one or the other, if it's "just because of DSL" or if there are other reasons involved. That's not to neglect DSL, but if DSL is the only reason for sticking to a flawed design, we really need to consider our options. |
Both part 1 and 2. Indeed they can be different, but how often does that happen? Should the default (i.e. working within one timezone) have to do more work in their rules to support this rare use case? Because that's the case now. We are imposing more work and more complexity on the users of OH who are least capable of adopting to it.
Only because the other languages have a helper library to provide a work around. It's a problem there too, we can just fix the problem on behalf of the end users in the helper library.
That's how Rules DSL works. There is no helper library. Rules DSL (and Groovy too I think) use the raw Java classes. If you change them for add-ons (for example) they change for Rules DSL users too. And again, the end users are the ones least capable of handling this complexity. We should be making their job easier, not harder. We especially shouldn't be making the default use case harder to support a rare use case. I can't speak to what Instant does or does not do for add-ons or other parts of OH but I can say that it makes the end user's experience worse. |
In that case we have a misunderstanding. For the specific (and quite normal) case where system and openHAB time-zone is the same, |
But without a wrapper here, |
This is an extension to #4351 so that
ItemStateUpdatedEvent
to havegetLastStateUpdate()
ItemStateChangedEvent
to havegetLastStateUpdate()
getLastStateChange()
The corresponding
lastStateUpdate
andlastStateChange
contexts are also available in RulesDSL.Resolve #4601