Skip to content

Conversation

lovery
Copy link
Contributor

@lovery lovery commented Mar 17, 2025

Description

Change the date and time format for time value which is inserted when persist method of an item is called.
Bellow is an example of a JSRule for testing the issue.

rules.JSRule({
    name: "Persist previous item state on change",
    triggers: triggers.ItemStateChangeTrigger("YOUR_ITEM_NAME"),
    execute: data => {
        oneSecondAgo = new Date(Date.now()); 
        oneSecondAgo.setSeconds(oneSecondAgo.getSeconds() - 1);
        items.getItem(data.itemName).persistence.persist(time.toZDT(oneSecondAgo), data.oldState);
    }
});

The default time format is '%Y-%m-%d %H:%M:%f' - check it here.
All other formats aren't supported by the HabPanel's graphics - the values don't appear on the graphic if the time is not in the upper format.

I tried one other solution, but since the format isn't specified anywhere, I didn't like it, because it could lead to the same problem as before:

         java.sql.Timestamp tsObj = new java.sql.Timestamp(date.toInstant().toEpochMilli());
         String timestamp = tsObj.toString();

Here is a link to a thread in OH community forum

Testing

Automatic built will be under the following folder:
https://openhab.jfrog.io/ui/native/libs-pullrequest-local/org/openhab/addons/bundles/

Here is also a link to a build that I made for OH 4.2 and 4.3

Correct existing data in SQL

In case someone wants to update their data in the SQLite, I am providing guidelines how to do that:

  1. Create a copy of your database or at least of the tables you are going to edit

  2. First you have to find the table in which the item is persisted in the SQLite with:
    SELECT ItemId, ItemName FROM items WHERE ItemName = 'XXXXXXXX';
    Check that you are getting the right id connected to your item.

  3. Check that you have mixed time values: SELECT time, value FROM itemXXXX;
    Keep in mind that you may have to add leading zeros to the id you get, I had ItemId - 256 and I had to add one leading 0, your case could be different.

  4. All my values started with 17, so I used this for in the where clause of my update statement like:
    UPDATE itemXXXX SET time = datetime(CAST(substr(time, 0, 11) as REAL), 'unixepoch', 'localtime') || '.' || substr(time, 11, 3) WHERE time LIKE '17%';

Fixes #18101

@lovery lovery requested review from a team and markus7017 as code owners March 17, 2025 17:17
Signed-off-by: Zhivka Dimova <zhivka.dimova@myforest.net>
@openhab-bot
Copy link
Collaborator

This pull request has been mentioned on openHAB Community. There might be relevant details there:

https://community.openhab.org/t/how-do-i-use-persistence-persit-in-javascript/161623/6

@jlaur jlaur changed the title [jdbc]: SQLite - Fix insert time format when using persist method of an item [jdbc] SQLite - Fix insert time format when using persist method of an item Mar 18, 2025
@jlaur jlaur added bug An unexpected problem or unintended behavior of an add-on (potentially) not backward compatible and removed (potentially) not backward compatible labels Apr 6, 2025
@jlaur
Copy link
Contributor

jlaur commented Apr 6, 2025

@lovery - thank you for the fix, and sorry for the long wait! I'm trying to understand this issue. I've checked this and my understanding now is that we're actually storing a formatted string (please correct me if I'm wrong). So to understand the difference in behavior, we need to look at this:

sqlTypes.put("tablePrimaryValue", "strftime('%Y-%m-%d %H:%M:%f' , 'now' , 'localtime')");

vs.

java.sql.Timestamp timestamp = new java.sql.Timestamp(date.toInstant().toEpochMilli());
Object[] params = { timestamp, storedVO.getValue() };

So as far as I can see, your fix will do the same formatting on Java side as done on SQL side for the doStoreItemValue overload without the ZonedDateTime parameter.

I'm wondering though if it would be safest to use the same strftime function in both cases? I'm worried about time-zone issues. The SQL version will convert a UTC timestamp to local time using the system time zone. I think your version will use the time zone provided in the ZonedDateTime? Can you try to run a small test setting your openHAB time zone in regional settings to a different time zone than your system time zone, and see if that will cause issues?

@jlaur jlaur added the awaiting feedback Awaiting feedback from the pull request author label Apr 21, 2025
lovery added 2 commits May 12, 2025 21:24
Signed-off-by: Zhivka Dimova <zhivka.dimova@myforest.net>
Signed-off-by: Zhivka Dimova <zhivka.dimova@myforest.net>
@lovery
Copy link
Contributor Author

lovery commented May 12, 2025

Hi @jlaur, you've understood is correctly, a formatted string is stored.
I've tested the current fix with one system time zone and other time zone selected in the OH settings and you are right the inserted time is NOT OK like this.

I re-wrote the code and used the strftime, but I had to use also the substr because the unixepoch modifier in the SQLite expects up to 10 signs, so it can't handle values with milliseconds.

@jlaur jlaur removed the awaiting feedback Awaiting feedback from the pull request author label May 12, 2025
@jlaur
Copy link
Contributor

jlaur commented May 12, 2025

I re-wrote the code and used the strftime, but I had to use also the substr because the unixepoch modifier in the SQLite expects up to 10 signs, so it can't handle values with milliseconds.

Perhaps that's because it expects number of seconds rather than milliseconds?

The unixepoch() function returns a unix timestamp - the number of seconds since 1970-01-01 00:00:00 UTC.

Maybe you could use date.toInstant().getEpochSecond() directly as a query parameter for:

strftime('%Y-%m-%d %H:%M:%f', ?, 'unixepoch', 'localtime')

Do you think that would work?

Signed-off-by: Zhivka Dimova <zhivka.dimova@myforest.net>
@lovery
Copy link
Contributor Author

lovery commented May 13, 2025

Maybe you could use date.toInstant().getEpochSecond() directly as a query parameter for:

strftime('%Y-%m-%d %H:%M:%f', ?, 'unixepoch', 'localtime')

Do you think that would work?

@jlaur Changed to use getEpochSecond(), and also I added a method for getting the milliseconds, instead of using the substr.

lovery added 2 commits May 14, 2025 14:15
Signed-off-by: Zhivka Dimova <zhivka.dimova@myforest.net>
Signed-off-by: Zhivka Dimova <zhivka.dimova@myforest.net>
Copy link
Contributor

@jlaur jlaur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to use getEpochSecond(), and also I added a method for getting the milliseconds, instead of using the substr.

Excellent, thanks for the simplification! We are almost there, just requesting one correction to comply with naming conventions (also reported by SAT). Please confirm that the new version is fully tested, and we are ready to merge. Thanks for your efforts!

Signed-off-by: Zhivka Dimova <zhivka.dimova@myforest.net>
@lovery
Copy link
Contributor Author

lovery commented May 14, 2025

@jlaur Fully tested the change, everything is good with it.

Copy link
Contributor

@jlaur jlaur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jlaur jlaur merged commit 6e0c43b into openhab:main May 14, 2025
2 checks passed
@jlaur jlaur added this to the 5.0 milestone May 14, 2025
@jlaur jlaur changed the title [jdbc] SQLite - Fix insert time format when using persist method of an item [jdbc] SQLite: Fix format when persisting item with timestamp May 14, 2025
@lovery lovery deleted the jdbc-fix-time branch May 15, 2025 06:29
phenix1990 pushed a commit to phenix1990/openhab-addons that referenced this pull request Jul 31, 2025
…n item (openhab#18407)

Signed-off-by: Zhivka Dimova <zhivka.dimova@myforest.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug An unexpected problem or unintended behavior of an add-on

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[jdbc-sqlite] <item>.persist(ZonedDateTime, State) stores epoch timestamp instead of DateTime format

3 participants