<item>.persistence.getAllStatesSince() doesn't work

I’ve got a DateTime item laatsteafsluitingopenhab (recording the last time openHAB was shut down). Trying to dig into the past doesn’t entirely work: <item>.persistence.getAllStatesSince() doesn’t do what I expect of it:

var datumitem = items["laatsteafsluitingopenhab"];
var daybeforeyesterday = new Date(new Date().getTime() - (48 * 60 * 60 * 1000));
var previoustates = datumitem.persistence.getAllStatesSince(daybeforeyesterday);

console.log("previous states: "+previoustates);
console.log("number of previous states: "+previoustates.length);
console.log("current state: "+datumitem.state);
console.log("previous state: "+datumitem.previousState);
console.log("daybeforeyesterday = "+daybeforeyesterday);

Output:

14:01:30.392 [INFO ] [utomation.jsscripting.rule.scratchpad] - previous states:
14:01:30.393 [INFO ] [utomation.jsscripting.rule.scratchpad] - number of previous states: 0
14:01:30.394 [INFO ] [utomation.jsscripting.rule.scratchpad] - current state: 2026-05-27T06:57:54.540+0200
14:01:30.394 [INFO ] [utomation.jsscripting.rule.scratchpad] - previous state: 2026-05-26T09:57:43.930+0200
14:01:30.396 [INFO ] [utomation.jsscripting.rule.scratchpad] - daybeforeyesterday = Mon May 25 2026 14:01:30 GMT+0200 (CEST)

What am I doing wrong?

What is your persistence definition for laatsteafsluitingopenhab?

I’ve tried a few times to wrap my head around this entire persinstence concept. But I keep failing.

This is what my persistence settings window looks like:

rrdj4 persistence configuration:

configurations:
  - items:
      - "*"
    strategies:
      - restoreOnStartup
      - everyChange
      - everyMinute
    filters: []
aliases: {}
cronStrategies:
  - name: everyMinute
    cronExpression: 0 * * * * ?
thresholdFilters: []
timeFilters: []
equalsFilters: []
includeFilters: []

Is that what you meant?

rrd4j does not store DateTime item types I believe. It is only for numeric values, see documentation.
You can use another db if you absolutely want this.

An alternative is to use mapdb to get the last value before shutdown.

The challenge I also see is how to make sure to only persist when shutting down. How do you update that laatsteafsluitingopenhab item?

Aha, that works:

var datumitem = items["laatsteafsluitingopenhab"];
var daybeforeyesterday = new Date(new Date().getTime() - (10000 * 60 * 60 * 1000));
var previoustates = datumitem.persistence.getAllStatesSince(daybeforeyesterday, 'mapdb');

console.log("previous states: "+previoustates);
console.log("number of previous states: "+previoustates.length);
console.log("current state: "+datumitem.state);
console.log("previous state: "+datumitem.previousState);
console.log("daybeforeyesterday = "+daybeforeyesterday);
15:36:30.378 [INFO ] [utomation.jsscripting.rule.scratchpad] - previous states: PersistedItem (Timestamp=2026-05-23T05:36:51+02:00[Europe/Brussels], State=2026-05-27T06:57:54.540+0200)
15:36:30.380 [INFO ] [utomation.jsscripting.rule.scratchpad] - number of previous states: 1
15:36:30.382 [INFO ] [utomation.jsscripting.rule.scratchpad] - current state: 2026-05-27T06:57:54.540+0200
15:36:30.383 [INFO ] [utomation.jsscripting.rule.scratchpad] - previous state: 2026-05-26T09:57:43.930+0200
15:36:30.387 [INFO ] [utomation.jsscripting.rule.scratchpad] - daybeforeyesterday = Sat Apr 05 2025 23:36:30 GMT+0200 (CEST)

That is, more or less. Obviously, I’ve restarted openHAB more than once since 05/04/2025…

I’m confused why you need the persistence for this at all. My rule template calculates the last shutdown time when OH starts up again, every time OH starts up. MapDB always only saves the most recent value. It doesn’t save more than that. So the value in mapDB is always going to match the current state of the Item.

I see no point in using persistence for this if all you need is the most recent OH shutdown time.

In fact, you really get the last two shutdown times because the Item stores the last change too, assuming you have mapdb configured with restoreOnStartup.

The sequence of events would be as follows.

  1. OH shuts down
  2. OH begins startup
  3. Items are loaded
  4. restorOnStartup initializes laatsteafsluitingopenhab with the value the Item had before 1 (this is the shutdown time that occurred before 1)
  5. The rule enginee starts
  6. The Last Shutdown Timestamp rule runs and determines the time of step 1 based on the events.log and updates laatsteafsluitingopenhab with that time
  7. This change is recorded in mapdb

At this point:

  • laatsteafsluitingopenhab.state is the value from step 6
  • laatsteafsluitingopenhab.previousState is the value from step 4
  • laatsteafsluitingopenhab.persistence.getAllStatesSince(daybeforeyesterday) is an array with a single value which is the value from step 6

So the use of mapdb does buy you something here as it’s needed to do the restoreOnStartup which gives you the previousState on the Item. But you don’t need to use persistence to get that value and in fact, with mapdb, it won’t even get you that value.

So this feels like an XY Problem. Why are you trying to use getAllStatesSince here?

Some stylaistic notes about the code.

There are several ways to access an Item like this:

items.laatsteafsluitingopenhab
items["laatsteafsluitingopenhab"]
items.getItem('laatsteafsluitingopenhab')

The advantage of the first and last option is I think the intellisence built into the MainUI code editor can more reliably autocomplete the Item name (ctrl-space).

image

One of the worse parts of dealing with dates and times is dealing with “magic” numbers. But this is why openHAB provides ZonedDateTime and why all the actions take that class. It becomes much more human readable. And when you add in time.toZDT() you have multi-tool to convert just about anything to a ZDT without resorting to tedious "number of hours * number of minutes * …: operations which require a higher mental load in the long run to read and understand later.

Alternative ways to calculate daybeforeyesterday

time.toZDT().minusDays(2) // time.toZDT() returns now, then subtract two days
time.toZDT().minusHours(48) // time.toZDT() returns now, then subtract 48 hours
time.toZDT('P-2D') // ISO8601 Duration added to now (negative number)
time.toZDT(time.Duration.ofDays(-2))  // Duration added to now (negative number)

Not only are these shorter to write, they just say what they do. It takes very little cognitive load to understand what the code does. And more complicated calculations become much easier. Let’s say you want two days ago at 8:00 AM. time.toZDT('8:00 AM').minusDays(2).

Let’s say you want to know how much time has passed between the last two shutdowns.

const shutdowTimes = items.laatsteafsluitingopenhab.persistence.getAllStatesSince(time.toZDT('P-90D')); // let's go back 90 days, OH can remain running for a long time
const lastTwo = shutdownTimes.slice(-2); // get the two most recent entries
const delta = time.Duration.between(lastTwo[0], lastTwo[1]); // time between the last two timestamps

Of course the above code assumes you are using something besides mapdb which can save more than one past value.

Thanks for the tip!

I wanted a better view on previous restarts, to better analyze unexpected behavior of the Shelly binding.

But the conclusion is that this is impossible for a DateTime Item?

You need a database for persistence that can both save a DateTime Item and save more than one entry per Item. That excludes mapdb and rrd4j. But any of the remaining persistence add-ons can do the job. But they all will require a bit more work, though maybe not for the SQLite add-on which should be self contained.