openhab-core icon indicating copy to clipboard operation
openhab-core copied to clipboard

[core] Use `Instant` internally for `DateTimeType`

Open jlaur opened this issue 2 years ago • 5 comments

Draft proposal for switching DateTimeType to use Instant internally rather than ZonedDateTime.

This will effectively strip time-zone information from the source of the DateTimeType and leave it to consumers to apply time-zone at the moment of presentation, according to the configured time-zone in openHAB regional settings or in the browser.

Example DSL rule:

var dt = ZonedDateTime.of(2024, 4, 26, 0, 0, 0, 0, ZoneId.systemDefault())
DateTimeTest1.postUpdate(new DateTimeType(dt))
DateTimeTest2.postUpdate(new DateTimeType(dt.toInstant().atZone(ZoneId.of("UTC"))))
DateTimeTest3.postUpdate(new DateTimeType(dt.toInstant()))

Previous result with system time-zone CET/DST:

[openhab.event.ItemStateChangedEvent ] - Item 'DateTimeTest1' changed from NULL to 2024-04-26T00:00:00.000+0200
[openhab.event.ItemStateChangedEvent ] - Item 'DateTimeTest2' changed from NULL to 2024-04-25T22:00:00.000+0000

New result with same system time-zone:

[openhab.event.ItemStateChangedEvent ] - Item 'DateTimeTest1' changed from NULL to 2024-04-26T00:00:00.000+0200
[openhab.event.ItemStateChangedEvent ] - Item 'DateTimeTest2' changed from NULL to 2024-04-26T00:00:00.000+0200
[openhab.event.ItemStateChangedEvent ] - Item 'DateTimeTest3' changed from NULL to 2024-04-26T00:00:00.000+0200

Resolves #2898

jlaur avatar Apr 29 '23 22:04 jlaur

I hit a wall with this when realizing that toFullString() and toString() should probably format as UTC for consistency. However, I believe one of these is used by Main UI for display purposes, so to improve the display with correct time-zone rather breaking it by raw UTC format, we would need UI changes - see also https://github.com/openhab/openhab-core/issues/2898#issuecomment-1370230276.

I don't know if any @openhab/webui-maintainers can throw some light at what may be a possible way forward?

jlaur avatar Sep 19 '23 20:09 jlaur

@mherwege - seeing your work in #4169 I'm wondering if you can advise how to accomplish decoupling the time-zone + formatting of DateTimeType. The general idea is to reduce it to be only an Instant without time-zone information. Therefore the UI should no longer display the raw output of toString() / toFullString(). Instead it must use the configured time-zone from TimeZoneProvider for formatting the DateTime in local time.

Currently it's formatted like this: 2024-04-10T20:55:01.000+0200. The problem is that "+0200" is the time-zone provided when updating the value, not the current time-zone. I don't know how this formatting works in Main UI.

jlaur avatar Apr 10 '24 18:04 jlaur

@jlaur Main UI works with what it gets from the REST API. On the Items screen (items list), it will show the state exactly as it is received from the REST API /items endpoint. Here is an extract of such a response:

    {
        "link": "http://openhabian.local:8080/rest/items/PMD",
        "state": "2024-04-11T00:00:00.000+0200",
        "stateDescription": {
            "pattern": "%1$td-%1$tm-%1$tY",
            "readOnly": true,
            "options": []
        },
        "editable": true,
        "type": "DateTime",
        "name": "PMD",
        "label": "PMD",
        "category": "calendar",
        "tags": [],
        "groupNames": [
            "Afval"
        ]
    }

state is what gets shown in the items list.

The formatted state comes from the states event stream in the displayState field. It is a result of applying the stateDescription pattern, but that is done in core. Event stream extract:

data: {"Afval":{"state":"2024-04-10T00:00:00.000+0200","displayState":"10-04-2024","type":"DateTime"},"Papier":{"state":"2024-04-10T00:00:00.000+0200","displayState":"10-04-2024","type":"DateTime"},"Restafval":{"state":"2024-04-18T00:00:00.000+0200","displayState":"18-04-2024","type":"DateTime"},"PMD":{"state":"2024-04-11T00:00:00.000+0200","displayState":"11-04-2024","type":"DateTime"}}

displayState gets used in widgets when available.

So, to understand where state and displayState come from, one needs to look at the REST API code. According to https://github.com/openhab/openhab-core/blob/cbb458e0c3c35f353954f82031c5cd1b3943759c/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/internal/item/ItemResource.java#L953 state is added through the EnrichedItemDTOMapper here: https://github.com/openhab/openhab-core/blob/cbb458e0c3c35f353954f82031c5cd1b3943759c/bundles/org.openhab.core.io.rest.core/src/main/java/org/openhab/core/io/rest/core/item/EnrichedItemDTOMapper.java#L81 So it is simply using the toFullString() method on the state of the item.

mherwege avatar Apr 11 '24 15:04 mherwege

@mherwege - many thanks for your insights. I will have a closer look at this soon.

jlaur avatar Apr 11 '24 20:04 jlaur