diff --git a/bundles/org.openhab.core.persistence/src/main/java/org/openhab/core/persistence/extensions/PersistenceExtensions.java b/bundles/org.openhab.core.persistence/src/main/java/org/openhab/core/persistence/extensions/PersistenceExtensions.java
index 034993e4fb..4d43fd92b3 100644
--- a/bundles/org.openhab.core.persistence/src/main/java/org/openhab/core/persistence/extensions/PersistenceExtensions.java
+++ b/bundles/org.openhab.core.persistence/src/main/java/org/openhab/core/persistence/extensions/PersistenceExtensions.java
@@ -1150,6 +1150,76 @@ public class PersistenceExtensions {
}
}
+ /**
+ * Gets the number of changes in historic data points of a given {@link Item} from a point in time until now.
+ * The default {@link PersistenceService} is used.
+ *
+ * @param item the {@link Item} to query
+ * @param begin the beginning point in time
+ * @return the number of state changes for this item
+ */
+ public static long countStateChangesSince(Item item, ZonedDateTime begin) {
+ return countStateChangesSince(item, begin, getDefaultServiceId());
+ }
+
+ /**
+ * Gets the number of changes in historic data points of a given {@link Item} from a point in time until now.
+ * The {@link PersistenceService} identified by the serviceId
is used.
+ *
+ * @param item the {@link Item} to query
+ * @param begin the beginning point in time
+ * @param serviceId the name of the {@link PersistenceService} to use
+ * @return the number of state changes for this item
+ */
+ public static long countStateChangesSince(Item item, ZonedDateTime begin, String serviceId) {
+ return countStateChangesBetween(item, begin, null, serviceId);
+ }
+
+ /**
+ * Gets the number of changes in historic data points of a given {@link Item} between two points in time.
+ * The default {@link PersistenceService} is used.
+ *
+ * @param item the {@link Item} to query
+ * @param begin the beginning point in time
+ * @param end the end point in time
+ * @return the number of state changes for this item
+ */
+ public static long countStateChangesBetween(Item item, ZonedDateTime begin, @Nullable ZonedDateTime end) {
+ return countStateChangesBetween(item, begin, end, getDefaultServiceId());
+ }
+
+ /**
+ * Gets the number of changes in historic data points of a given {@link Item} between two points in time.
+ * The {@link PersistenceService} identified by the serviceId
is used.
+ *
+ * @param item the {@link Item} to query
+ * @param begin the beginning point in time
+ * @param end the end point in time
+ * @param serviceId the name of the {@link PersistenceService} to use
+ * @return the number of state changes for this item
+ */
+ public static long countStateChangesBetween(Item item, ZonedDateTime begin, @Nullable ZonedDateTime end,
+ String serviceId) {
+ Iterable result = getAllStatesBetween(item, begin, end, serviceId);
+ Iterator it = result.iterator();
+
+ if (!it.hasNext()) {
+ return 0;
+ }
+
+ long count = 0;
+ State previousState = it.next().getState();
+ while (it.hasNext()) {
+ HistoricItem historicItem = it.next();
+ State state = historicItem.getState();
+ if (!state.equals(previousState)) {
+ previousState = state;
+ count++;
+ }
+ }
+ return count;
+ }
+
private static @Nullable PersistenceService getService(String serviceId) {
PersistenceService service = null;
if (registry != null) {
diff --git a/bundles/org.openhab.core.persistence/src/test/java/org/openhab/core/persistence/extensions/PersistenceExtensionsTest.java b/bundles/org.openhab.core.persistence/src/test/java/org/openhab/core/persistence/extensions/PersistenceExtensionsTest.java
index b983db6ad3..698c0cc5ad 100644
--- a/bundles/org.openhab.core.persistence/src/test/java/org/openhab/core/persistence/extensions/PersistenceExtensionsTest.java
+++ b/bundles/org.openhab.core.persistence/src/test/java/org/openhab/core/persistence/extensions/PersistenceExtensionsTest.java
@@ -951,4 +951,41 @@ public class PersistenceExtensionsTest {
ZonedDateTime.of(2000, 1, 1, 0, 0, 0, 0, ZoneId.systemDefault()));
assertEquals(0, counts);
}
+
+ @Test
+ public void testCountStateChangesSince() {
+ long counts = PersistenceExtensions.countStateChangesSince(numberItem,
+ ZonedDateTime.of(1980, 1, 1, 0, 0, 0, 0, ZoneId.systemDefault()), TestPersistenceService.ID);
+ assertEquals(32, counts);
+
+ counts = PersistenceExtensions.countStateChangesSince(numberItem,
+ ZonedDateTime.of(2007, 1, 1, 0, 0, 0, 0, ZoneId.systemDefault()), TestPersistenceService.ID);
+ assertEquals(5, counts);
+
+ counts = PersistenceExtensions.countStateChangesSince(numberItem,
+ ZonedDateTime.of(2020, 1, 1, 0, 0, 0, 0, ZoneId.systemDefault()), TestPersistenceService.ID);
+ assertEquals(0, counts);
+
+ counts = PersistenceExtensions.countStateChangesSince(numberItem,
+ ZonedDateTime.of(2000, 1, 1, 0, 0, 0, 0, ZoneId.systemDefault()));
+ assertEquals(0, counts);
+ }
+
+ @Test
+ public void testCountStateChangesBetween() {
+ long counts = PersistenceExtensions.countStateChangesBetween(numberItem,
+ ZonedDateTime.of(1940, 1, 1, 0, 0, 0, 0, ZoneId.systemDefault()),
+ ZonedDateTime.of(1970, 1, 1, 0, 0, 0, 0, ZoneId.systemDefault()), TestPersistenceService.ID);
+ assertEquals(0, counts);
+
+ counts = PersistenceExtensions.countStateChangesBetween(numberItem,
+ ZonedDateTime.of(2005, 1, 1, 0, 0, 0, 0, ZoneId.systemDefault()),
+ ZonedDateTime.of(2011, 1, 1, 0, 0, 0, 0, ZoneId.systemDefault()), TestPersistenceService.ID);
+ assertEquals(6, counts);
+
+ counts = PersistenceExtensions.countStateChangesBetween(numberItem,
+ ZonedDateTime.of(2005, 1, 1, 0, 0, 0, 0, ZoneId.systemDefault()),
+ ZonedDateTime.of(2011, 1, 1, 0, 0, 0, 0, ZoneId.systemDefault()));
+ assertEquals(0, counts);
+ }
}