diff --git a/bundles/org.openhab.core.persistence/src/main/java/org/openhab/core/persistence/QueryablePersistenceService.java b/bundles/org.openhab.core.persistence/src/main/java/org/openhab/core/persistence/QueryablePersistenceService.java index e3e67bd6486..1313268f641 100644 --- a/bundles/org.openhab.core.persistence/src/main/java/org/openhab/core/persistence/QueryablePersistenceService.java +++ b/bundles/org.openhab.core.persistence/src/main/java/org/openhab/core/persistence/QueryablePersistenceService.java @@ -12,6 +12,8 @@ */ package org.openhab.core.persistence; +import java.time.Instant; +import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.Iterator; import java.util.Set; @@ -22,7 +24,6 @@ import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.persistence.FilterCriteria.Ordering; import org.openhab.core.types.State; -import org.openhab.core.types.UnDefType; /** * A queryable persistence service which can be used to store and retrieve @@ -65,6 +66,11 @@ default Iterable query(FilterCriteria filter, @Nullable String ali FilterCriteria aliasFilter = new FilterCriteria(filter).setItemName(alias); return StreamSupport.stream(query(aliasFilter).spliterator(), false).map(hi -> new HistoricItem() { + @Override + public Instant getInstant() { + return hi.getInstant(); + } + @Override public ZonedDateTime getTimestamp() { return hi.getTimestamp(); @@ -111,8 +117,8 @@ public String getName() { * @return a {@link PersistedItem} or null if the item has not been persisted */ default @Nullable PersistedItem persistedItem(String itemName, @Nullable String alias) { - State currentState = UnDefType.NULL; - ZonedDateTime lastUpdate = null; + State currentState; + Instant lastUpdate; FilterCriteria filter = new FilterCriteria().setItemName(itemName).setEndDate(ZonedDateTime.now()) .setOrdering(Ordering.DESCENDING).setPageSize(1).setPageNumber(0); @@ -120,19 +126,23 @@ public String getName() { if (it.hasNext()) { HistoricItem historicItem = it.next(); currentState = historicItem.getState(); - lastUpdate = historicItem.getTimestamp(); + lastUpdate = historicItem.getInstant(); } else { return null; } final State state = currentState; - final ZonedDateTime lastStateUpdate = lastUpdate; + final Instant lastStateUpdate = lastUpdate; return new PersistedItem() { + @Override + public Instant getInstant() { + return lastStateUpdate; + } @Override public ZonedDateTime getTimestamp() { - return lastStateUpdate; + return lastStateUpdate.atZone(ZoneId.systemDefault()); } @Override 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 e132e2a8382..68e4aa7c119 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 @@ -15,6 +15,7 @@ import java.math.BigDecimal; import java.math.MathContext; import java.time.Duration; +import java.time.Instant; import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.ArrayList; @@ -71,6 +72,7 @@ * @author Mark Herwege - add median methods * @author Mark Herwege - use item lastChange and lastUpdate methods if not in peristence * @author Mark Herwege - add Riemann sum methods + * @author Jörg Sautter - use Instant instead of ZonedDateTime in Riemann sum methods */ @Component(immediate = true) @NonNullByDefault @@ -1926,7 +1928,7 @@ private static void internalPersist(Item item, TimeSeries timeSeries, @Nullable private static @Nullable BigDecimal average(ZonedDateTime begin, ZonedDateTime end, Iterator it, @Nullable Unit unit, @Nullable RiemannType type) { - BigDecimal sum = riemannSum(begin, end, it, unit, type); + BigDecimal sum = riemannSum(begin.toInstant(), end.toInstant(), it, unit, type); BigDecimal totalDuration = BigDecimal.valueOf(Duration.between(begin, end).toMillis()); if (totalDuration.signum() == 0) { return null; @@ -2195,35 +2197,39 @@ private static void internalPersist(Item item, TimeSeries timeSeries, @Nullable Item baseItem = item instanceof GroupItem groupItem ? groupItem.getBaseItem() : item; Unit unit = (baseItem instanceof NumberItem numberItem) && (numberItem.getUnit() instanceof Unit numberItemUnit) ? numberItemUnit.getSystemUnit() : null; - BigDecimal sum = riemannSum(beginTime, endTime, it, unit, type).scaleByPowerOfTen(-3); + BigDecimal sum = riemannSum(beginTime.toInstant(), endTime.toInstant(), it, unit, type).scaleByPowerOfTen(-3); if (unit != null) { return new QuantityType<>(sum, unit.multiply(Units.SECOND)); } return new DecimalType(sum); } - private static BigDecimal riemannSum(ZonedDateTime begin, ZonedDateTime end, Iterator it, - @Nullable Unit unit, @Nullable RiemannType type) { + private static BigDecimal riemannSum(Instant begin, Instant end, Iterator it, @Nullable Unit unit, + @Nullable RiemannType type) { RiemannType riemannType = type == null ? RiemannType.LEFT : type; BigDecimal sum = BigDecimal.ZERO; HistoricItem prevItem = null; - HistoricItem nextItem = null; + HistoricItem nextItem; DecimalType prevState = null; - DecimalType nextState = null; + DecimalType nextState; + Instant prevInstant = null; + Instant nextInstant; Duration prevDuration = Duration.ZERO; - Duration nextDuration = Duration.ZERO; + Duration nextDuration; boolean midpointStartBucket = true; // The start and end buckets for the midpoint calculation should be // considered for the full length, this flag is used to find the start // bucket if ((riemannType == RiemannType.MIDPOINT) && it.hasNext()) { prevItem = it.next(); + prevInstant = prevItem.getInstant(); prevState = getPersistedValue(prevItem, unit); } while (it.hasNext()) { nextItem = it.next(); + nextInstant = nextItem.getInstant(); BigDecimal weight = BigDecimal.ZERO; BigDecimal value = BigDecimal.ZERO; switch (riemannType) { @@ -2232,24 +2238,24 @@ private static BigDecimal riemannSum(ZonedDateTime begin, ZonedDateTime end, Ite prevState = getPersistedValue(prevItem, unit); if (prevState != null) { value = prevState.toBigDecimal(); - weight = BigDecimal.valueOf( - Duration.between(prevItem.getTimestamp(), nextItem.getTimestamp()).toMillis()); + weight = BigDecimal.valueOf(Duration.between(prevInstant, nextInstant).toMillis()); } } prevItem = nextItem; + prevInstant = nextInstant; break; case RIGHT: nextState = getPersistedValue(nextItem, unit); if (nextState != null) { value = nextState.toBigDecimal(); if (prevItem == null) { - weight = BigDecimal.valueOf(Duration.between(begin, nextItem.getTimestamp()).toMillis()); + weight = BigDecimal.valueOf(Duration.between(begin, nextInstant).toMillis()); } else { - weight = BigDecimal.valueOf( - Duration.between(prevItem.getTimestamp(), nextItem.getTimestamp()).toMillis()); + weight = BigDecimal.valueOf(Duration.between(prevInstant, nextInstant).toMillis()); } } prevItem = nextItem; + prevInstant = nextInstant; break; case TRAPEZOIDAL: if (prevItem != null) { @@ -2258,11 +2264,11 @@ private static BigDecimal riemannSum(ZonedDateTime begin, ZonedDateTime end, Ite if (prevState != null && nextState != null) { value = prevState.toBigDecimal().add(nextState.toBigDecimal()) .divide(BigDecimal.valueOf(2)); - weight = BigDecimal.valueOf( - Duration.between(prevItem.getTimestamp(), nextItem.getTimestamp()).toMillis()); + weight = BigDecimal.valueOf(Duration.between(prevInstant, nextInstant).toMillis()); } } prevItem = nextItem; + prevInstant = nextInstant; break; case MIDPOINT: if (prevItem != null) { @@ -2272,12 +2278,12 @@ private static BigDecimal riemannSum(ZonedDateTime begin, ZonedDateTime end, Ite if (midpointStartBucket && !prevDuration.isZero() && prevState != null) { // Add half of the start bucket with the start value (left approximation) sum = sum.add(prevState.toBigDecimal() - .multiply(BigDecimal.valueOf(prevDuration.dividedBy(2).toMillis()))); + .multiply(BigDecimal.valueOf(prevDuration.toMillis() / 2))); midpointStartBucket = false; } - nextDuration = Duration.between(prevItem.getTimestamp(), nextItem.getTimestamp()); + nextDuration = Duration.between(prevInstant, nextInstant); weight = prevDuration.isZero() || nextDuration.isZero() ? BigDecimal.ZERO - : BigDecimal.valueOf(prevDuration.plus(nextDuration).dividedBy(2).toMillis()); + : BigDecimal.valueOf(prevDuration.plus(nextDuration).toMillis() / 2); if (!nextDuration.isZero()) { prevDuration = nextDuration; } @@ -2285,6 +2291,7 @@ private static BigDecimal riemannSum(ZonedDateTime begin, ZonedDateTime end, Ite } } prevItem = nextItem; + prevInstant = nextInstant; break; } sum = sum.add(value.multiply(weight)); @@ -2295,7 +2302,7 @@ private static BigDecimal riemannSum(ZonedDateTime begin, ZonedDateTime end, Ite DecimalType dtState = getPersistedValue(prevItem, unit); if (dtState != null) { BigDecimal value = dtState.toBigDecimal(); - BigDecimal weight = BigDecimal.valueOf(prevDuration.dividedBy(2).toMillis()); + BigDecimal weight = BigDecimal.valueOf(prevDuration.toMillis() / 2); sum = sum.add(value.multiply(weight)); } }