[persistence] Implement HistoricItem.getInstant (#17578)

Signed-off-by: Jörg Sautter <joerg.sautter@gmx.net>
Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
This commit is contained in:
joerg1985 2024-10-25 22:59:22 +02:00 committed by Ciprian Pascu
parent 9ad7aab7d1
commit b95561ed23
15 changed files with 105 additions and 61 deletions

View File

@ -451,7 +451,7 @@ public abstract class AbstractDynamoDBItem<T> implements DynamoDBItem<T> {
if (deserializedState == null) { if (deserializedState == null) {
return null; return null;
} }
return new DynamoDBHistoricItem(getName(), deserializedState, getTime()); return new DynamoDBHistoricItem(getName(), deserializedState, getTime().toInstant());
} catch (Exception e) { } catch (Exception e) {
logger.trace("Failed to convert state '{}' to item {} {}: {} {}. Data persisted with incompatible item.", logger.trace("Failed to convert state '{}' to item {} {}: {} {}. Data persisted with incompatible item.",
this.state, item.getClass().getSimpleName(), item.getName(), e.getClass().getSimpleName(), this.state, item.getClass().getSimpleName(), item.getName(), e.getClass().getSimpleName(),

View File

@ -12,6 +12,7 @@
*/ */
package org.openhab.persistence.dynamodb.internal; package org.openhab.persistence.dynamodb.internal;
import java.time.Instant;
import java.time.ZoneId; import java.time.ZoneId;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
@ -33,12 +34,12 @@ public class DynamoDBHistoricItem implements HistoricItem {
private final String name; private final String name;
private final State state; private final State state;
private final ZonedDateTime timestamp; private final Instant instant;
public DynamoDBHistoricItem(String name, State state, ZonedDateTime timestamp) { public DynamoDBHistoricItem(String name, State state, Instant instant) {
this.name = name; this.name = name;
this.state = state; this.state = state;
this.timestamp = timestamp; this.instant = instant;
} }
@Override @Override
@ -48,7 +49,12 @@ public class DynamoDBHistoricItem implements HistoricItem {
@Override @Override
public ZonedDateTime getTimestamp() { public ZonedDateTime getTimestamp() {
return timestamp; return instant.atZone(ZoneId.systemDefault());
}
@Override
public Instant getInstant() {
return instant;
} }
@Override @Override
@ -58,6 +64,6 @@ public class DynamoDBHistoricItem implements HistoricItem {
@Override @Override
public String toString() { public String toString() {
return name + ": " + DATEFORMATTER.format(timestamp) + ": " + state.toString(); return name + ": " + DATEFORMATTER.format(getTimestamp()) + ": " + state.toString();
} }
} }

View File

@ -15,7 +15,6 @@ package org.openhab.persistence.influxdb;
import static org.openhab.persistence.influxdb.internal.InfluxDBConstants.*; import static org.openhab.persistence.influxdb.internal.InfluxDBConstants.*;
import java.time.Instant; import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -255,8 +254,7 @@ public class InfluxDBPersistenceService implements ModifiablePersistenceService
private HistoricItem mapRowToHistoricItem(InfluxDBRepository.InfluxRow row) { private HistoricItem mapRowToHistoricItem(InfluxDBRepository.InfluxRow row) {
State state = InfluxDBStateConvertUtils.objectToState(row.value(), row.itemName(), itemRegistry); State state = InfluxDBStateConvertUtils.objectToState(row.value(), row.itemName(), itemRegistry);
return new InfluxDBHistoricItem(row.itemName(), state, return new InfluxDBHistoricItem(row.itemName(), state, row.time());
ZonedDateTime.ofInstant(row.time(), ZoneId.systemDefault()));
} }
@Override @Override

View File

@ -13,6 +13,8 @@
package org.openhab.persistence.influxdb.internal; package org.openhab.persistence.influxdb.internal;
import java.text.DateFormat; import java.text.DateFormat;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
@ -30,12 +32,12 @@ public class InfluxDBHistoricItem implements HistoricItem {
private String name = ""; private String name = "";
private final State state; private final State state;
private final ZonedDateTime timestamp; private final Instant instant;
public InfluxDBHistoricItem(String name, State state, ZonedDateTime timestamp) { public InfluxDBHistoricItem(String name, State state, Instant instant) {
this.name = name; this.name = name;
this.state = state; this.state = state;
this.timestamp = timestamp; this.instant = instant;
} }
@Override @Override
@ -54,11 +56,16 @@ public class InfluxDBHistoricItem implements HistoricItem {
@Override @Override
public ZonedDateTime getTimestamp() { public ZonedDateTime getTimestamp() {
return timestamp; return instant.atZone(ZoneId.systemDefault());
}
@Override
public Instant getInstant() {
return instant;
} }
@Override @Override
public String toString() { public String toString() {
return DateFormat.getDateTimeInstance().format(timestamp) + ": " + name + " -> " + state.toString(); return DateFormat.getDateTimeInstance().format(getTimestamp()) + ": " + name + " -> " + state.toString();
} }
} }

View File

@ -475,7 +475,7 @@ public class JdbcBaseDAO {
String itemName = item.getName(); String itemName = item.getName();
Unit<? extends Quantity<?>> unit = item instanceof NumberItem numberItem ? numberItem.getUnit() : null; Unit<? extends Quantity<?>> unit = item instanceof NumberItem numberItem ? numberItem.getUnit() : null;
return m.stream() return m.stream()
.map(o -> new JdbcHistoricItem(itemName, objectAsState(item, unit, o[1]), objectAsZonedDateTime(o[0]))) .map(o -> new JdbcHistoricItem(itemName, objectAsState(item, unit, o[1]), objectAsInstant(o[0])))
.collect(Collectors.<HistoricItem> toList()); .collect(Collectors.<HistoricItem> toList());
} }
@ -684,7 +684,7 @@ public class JdbcBaseDAO {
} }
return unit == null ? DecimalType.valueOf(objectAsString(v)) : QuantityType.valueOf(objectAsString(v)); return unit == null ? DecimalType.valueOf(objectAsString(v)) : QuantityType.valueOf(objectAsString(v));
} else if (item instanceof DateTimeItem) { } else if (item instanceof DateTimeItem) {
return new DateTimeType(objectAsZonedDateTime(v)); return new DateTimeType(objectAsInstant(v).atZone(ZoneId.systemDefault()));
} else if (item instanceof ColorItem) { } else if (item instanceof ColorItem) {
return HSBType.valueOf(objectAsString(v)); return HSBType.valueOf(objectAsString(v));
} else if (item instanceof DimmerItem || item instanceof RollershutterItem) { } else if (item instanceof DimmerItem || item instanceof RollershutterItem) {
@ -710,20 +710,19 @@ public class JdbcBaseDAO {
} }
} }
protected ZonedDateTime objectAsZonedDateTime(Object v) { protected Instant objectAsInstant(Object v) {
if (v instanceof Long) { if (v instanceof Long) {
return ZonedDateTime.ofInstant(Instant.ofEpochMilli(((Number) v).longValue()), ZoneId.systemDefault()); return Instant.ofEpochMilli(((Number) v).longValue());
} else if (v instanceof java.sql.Date objectAsDate) { } else if (v instanceof java.sql.Date objectAsDate) {
return ZonedDateTime.ofInstant(Instant.ofEpochMilli(objectAsDate.getTime()), ZoneId.systemDefault()); return Instant.ofEpochMilli(objectAsDate.getTime());
} else if (v instanceof LocalDateTime objectAsLocalDateTime) { } else if (v instanceof LocalDateTime objectAsLocalDateTime) {
return objectAsLocalDateTime.atZone(ZoneId.systemDefault()); return objectAsLocalDateTime.atZone(ZoneId.systemDefault()).toInstant();
} else if (v instanceof Instant objectAsInstant) { } else if (v instanceof Instant objectAsInstant) {
return objectAsInstant.atZone(ZoneId.systemDefault()); return objectAsInstant;
} else if (v instanceof java.sql.Timestamp objectAsTimestamp) { } else if (v instanceof java.sql.Timestamp objectAsTimestamp) {
return objectAsTimestamp.toInstant().atZone(ZoneId.systemDefault()); return objectAsTimestamp.toInstant();
} else if (v instanceof java.lang.String objectAsString) { } else if (v instanceof java.lang.String objectAsString) {
return ZonedDateTime.ofInstant(java.sql.Timestamp.valueOf(objectAsString).toInstant(), return java.sql.Timestamp.valueOf(objectAsString).toInstant();
ZoneId.systemDefault());
} }
throw new UnsupportedOperationException("Date of type '" + v.getClass().getName() + "' is not supported"); throw new UnsupportedOperationException("Date of type '" + v.getClass().getName() + "' is not supported");
} }

View File

@ -13,6 +13,7 @@
package org.openhab.persistence.jdbc.internal.db; package org.openhab.persistence.jdbc.internal.db;
import java.sql.SQLException; import java.sql.SQLException;
import java.time.Instant;
import java.time.ZoneId; import java.time.ZoneId;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.List; import java.util.List;
@ -287,16 +288,16 @@ public class JdbcOracleDAO extends JdbcBaseDAO {
} }
@Override @Override
protected ZonedDateTime objectAsZonedDateTime(Object v) { protected Instant objectAsInstant(Object v) {
if (v instanceof TIMESTAMP objectAsOracleTimestamp) { if (v instanceof TIMESTAMP objectAsOracleTimestamp) {
try { try {
return objectAsOracleTimestamp.timestampValue().toInstant().atZone(ZoneId.systemDefault()); return objectAsOracleTimestamp.timestampValue().toInstant();
} catch (SQLException e) { } catch (SQLException e) {
throw new UnsupportedOperationException("Date of type '" + v.getClass().getName() throw new UnsupportedOperationException("Date of type '" + v.getClass().getName()
+ "', no Timestamp representation exists for '" + objectAsOracleTimestamp.toString() + "'"); + "', no Timestamp representation exists for '" + objectAsOracleTimestamp.toString() + "'");
} }
} else { } else {
return super.objectAsZonedDateTime(v); return super.objectAsInstant(v);
} }
} }
} }

View File

@ -12,6 +12,8 @@
*/ */
package org.openhab.persistence.jdbc.internal.dto; package org.openhab.persistence.jdbc.internal.dto;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
@ -28,12 +30,12 @@ public class JdbcHistoricItem implements HistoricItem {
private final String name; private final String name;
private final State state; private final State state;
private final ZonedDateTime timestamp; private final Instant instant;
public JdbcHistoricItem(String name, State state, ZonedDateTime timestamp) { public JdbcHistoricItem(String name, State state, Instant instant) {
this.name = name; this.name = name;
this.state = state; this.state = state;
this.timestamp = timestamp; this.instant = instant;
} }
@Override @Override
@ -48,7 +50,12 @@ public class JdbcHistoricItem implements HistoricItem {
@Override @Override
public ZonedDateTime getTimestamp() { public ZonedDateTime getTimestamp() {
return timestamp; return instant.atZone(ZoneId.systemDefault());
}
@Override
public Instant getInstant() {
return instant;
} }
@Override @Override
@ -59,7 +66,7 @@ public class JdbcHistoricItem implements HistoricItem {
builder.append(", state="); builder.append(", state=");
builder.append(state); builder.append(state);
builder.append(", timestamp="); builder.append(", timestamp=");
builder.append(timestamp); builder.append(getTimestamp());
builder.append("]"); builder.append("]");
return builder.toString(); return builder.toString();
} }

View File

@ -61,12 +61,12 @@ public class JpaHistoricItem implements HistoricItem {
private final String name; private final String name;
private final State state; private final State state;
private final ZonedDateTime timestamp; private final Instant instant;
public JpaHistoricItem(String name, State state, ZonedDateTime timestamp) { public JpaHistoricItem(String name, State state, Instant instant) {
this.name = name; this.name = name;
this.state = state; this.state = state;
this.timestamp = timestamp; this.instant = instant;
} }
@Override @Override
@ -76,7 +76,12 @@ public class JpaHistoricItem implements HistoricItem {
@Override @Override
public ZonedDateTime getTimestamp() { public ZonedDateTime getTimestamp() {
return timestamp; return instant.atZone(ZoneId.systemDefault());
}
@Override
public Instant getInstant() {
return instant;
} }
@Override @Override
@ -86,7 +91,7 @@ public class JpaHistoricItem implements HistoricItem {
@Override @Override
public String toString() { public String toString() {
return DateFormat.getDateTimeInstance().format(timestamp) + ": " + name + " -> " + state.toString(); return DateFormat.getDateTimeInstance().format(getTimestamp()) + ": " + name + " -> " + state;
} }
/** /**
@ -156,6 +161,6 @@ public class JpaHistoricItem implements HistoricItem {
state = new StringType(pItem.getValue()); state = new StringType(pItem.getValue());
} }
return new JpaHistoricItem(item.getName(), state, pItem.getTimestamp()); return new JpaHistoricItem(item.getName(), state, pItem.getInstant());
} }
} }

View File

@ -13,6 +13,7 @@
package org.openhab.persistence.jpa.internal.model; package org.openhab.persistence.jpa.internal.model;
import java.text.DateFormat; import java.text.DateFormat;
import java.time.Instant;
import java.time.ZoneId; import java.time.ZoneId;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.Date; import java.util.Date;
@ -88,6 +89,11 @@ public class JpaPersistentItem implements HistoricItem {
this.timestamp = timestamp; this.timestamp = timestamp;
} }
@Override
public Instant getInstant() {
return timestamp.toInstant();
}
public String getValue() { public String getValue() {
return value; return value;
} }

View File

@ -13,6 +13,7 @@
package org.openhab.persistence.mapdb.internal; package org.openhab.persistence.mapdb.internal;
import java.text.DateFormat; import java.text.DateFormat;
import java.time.Instant;
import java.time.ZoneId; import java.time.ZoneId;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.Date; import java.util.Date;
@ -64,6 +65,11 @@ public class MapDbItem implements HistoricItem, PersistenceItemInfo {
this.timestamp = timestamp; this.timestamp = timestamp;
} }
@Override
public Instant getInstant() {
return timestamp.toInstant();
}
@Override @Override
public String toString() { public String toString() {
return DateFormat.getDateTimeInstance().format(timestamp) + ": " + name + " -> " + state.toString(); return DateFormat.getDateTimeInstance().format(timestamp) + ": " + name + " -> " + state.toString();

View File

@ -13,6 +13,8 @@
package org.openhab.persistence.mongodb.internal; package org.openhab.persistence.mongodb.internal;
import java.text.DateFormat; import java.text.DateFormat;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.Date; import java.util.Date;
@ -30,12 +32,12 @@ public class MongoDBItem implements HistoricItem {
private final String name; private final String name;
private final State state; private final State state;
private final ZonedDateTime timestamp; private final Instant instant;
public MongoDBItem(String name, State state, ZonedDateTime timestamp) { public MongoDBItem(String name, State state, Instant instant) {
this.name = name; this.name = name;
this.state = state; this.state = state;
this.timestamp = timestamp; this.instant = instant;
} }
@Override @Override
@ -50,12 +52,17 @@ public class MongoDBItem implements HistoricItem {
@Override @Override
public ZonedDateTime getTimestamp() { public ZonedDateTime getTimestamp() {
return timestamp; return instant.atZone(ZoneId.systemDefault());
}
@Override
public Instant getInstant() {
return instant;
} }
@Override @Override
public String toString() { public String toString() {
Date date = Date.from(timestamp.toInstant()); Date date = Date.from(instant);
return DateFormat.getDateTimeInstance().format(date) + ": " + name + " -> " + state.toString(); return DateFormat.getDateTimeInstance().format(date) + ": " + name + " -> " + state;
} }
} }

View File

@ -12,7 +12,6 @@
*/ */
package org.openhab.persistence.mongodb.internal; package org.openhab.persistence.mongodb.internal;
import java.time.ZoneId;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -287,8 +286,7 @@ public class MongoDBPersistenceService implements ModifiablePersistenceService {
final State state = MongoDBTypeConversions.getStateFromDocument(item, obj); final State state = MongoDBTypeConversions.getStateFromDocument(item, obj);
items.add(new MongoDBItem(realItemName, state, ZonedDateTime items.add(new MongoDBItem(realItemName, state, obj.getDate(MongoDBFields.FIELD_TIMESTAMP).toInstant()));
.ofInstant(obj.getDate(MongoDBFields.FIELD_TIMESTAMP).toInstant(), ZoneId.systemDefault())));
} }
} finally { } finally {
if (cursor != null) { if (cursor != null) {

View File

@ -16,6 +16,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import java.text.DateFormat; import java.text.DateFormat;
import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.ZoneId; import java.time.ZoneId;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
@ -798,7 +799,7 @@ public class MongoDBPersistenceServiceTest {
@Test @Test
public void testHistoricItemToString() { public void testHistoricItemToString() {
// Preparation // Preparation
ZonedDateTime now = ZonedDateTime.now(); Instant now = Instant.now();
HistoricItem item = new MongoDBItem("TestItem", new DecimalType(10.1), now); HistoricItem item = new MongoDBItem("TestItem", new DecimalType(10.1), now);
// Execution // Execution
@ -806,7 +807,7 @@ public class MongoDBPersistenceServiceTest {
// Verification // Verification
// Jan 29, 2024, 8:43:26 PM: TestItem -> 10.1 // Jan 29, 2024, 8:43:26 PM: TestItem -> 10.1
String expected = DateFormat.getDateTimeInstance().format(Date.from(now.toInstant())) + ": TestItem -> 10.1"; String expected = DateFormat.getDateTimeInstance().format(Date.from(now)) + ": TestItem -> 10.1";
assertEquals(expected, result); assertEquals(expected, result);
} }

View File

@ -12,6 +12,8 @@
*/ */
package org.openhab.persistence.rrd4j.internal; package org.openhab.persistence.rrd4j.internal;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle; import java.time.format.FormatStyle;
@ -32,12 +34,12 @@ public class RRD4jItem implements HistoricItem {
private final String name; private final String name;
private final State state; private final State state;
private final ZonedDateTime timestamp; private final Instant instant;
public RRD4jItem(String name, State state, ZonedDateTime timestamp) { public RRD4jItem(String name, State state, Instant instant) {
this.name = name; this.name = name;
this.state = state; this.state = state;
this.timestamp = timestamp; this.instant = instant;
} }
@Override @Override
@ -52,13 +54,18 @@ public class RRD4jItem implements HistoricItem {
@Override @Override
public ZonedDateTime getTimestamp() { public ZonedDateTime getTimestamp() {
return timestamp; return instant.atZone(ZoneId.systemDefault());
}
@Override
public Instant getInstant() {
return instant;
} }
@Override @Override
public String toString() { public String toString() {
return timestamp return getTimestamp()
.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withLocale(Locale.getDefault())) + ": " .format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withLocale(Locale.getDefault())) + ": "
+ name + " -> " + state.toString(); + name + " -> " + state;
} }
} }

View File

@ -17,7 +17,6 @@ import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -472,8 +471,7 @@ public class RRD4jPersistenceService implements QueryablePersistenceService {
double lastValue = db.getLastDatasourceValue(DATASOURCE_STATE); double lastValue = db.getLastDatasourceValue(DATASOURCE_STATE);
if (!Double.isNaN(lastValue)) { if (!Double.isNaN(lastValue)) {
HistoricItem rrd4jItem = new RRD4jItem(itemName, toState.apply(lastValue), HistoricItem rrd4jItem = new RRD4jItem(itemName, toState.apply(lastValue),
ZonedDateTime.ofInstant(Instant.ofEpochSecond(db.getLastArchiveUpdateTime()), Instant.ofEpochSecond(db.getLastArchiveUpdateTime()));
ZoneId.systemDefault()));
return List.of(rrd4jItem); return List.of(rrd4jItem);
} else { } else {
return List.of(); return List.of();
@ -502,7 +500,6 @@ public class RRD4jPersistenceService implements QueryablePersistenceService {
List<HistoricItem> items = new ArrayList<>(); List<HistoricItem> items = new ArrayList<>();
long ts = result.getFirstTimestamp(); long ts = result.getFirstTimestamp();
ZonedDateTime zdt = ZonedDateTime.ofInstant(Instant.ofEpochSecond(ts), ZoneId.systemDefault());
long step = result.getRowCount() > 1 ? result.getStep() : 0; long step = result.getRowCount() > 1 ? result.getStep() : 0;
double prevValue = Double.NaN; double prevValue = Double.NaN;
@ -518,10 +515,9 @@ public class RRD4jPersistenceService implements QueryablePersistenceService {
prevValue = value; prevValue = value;
} }
RRD4jItem rrd4jItem = new RRD4jItem(itemName, state, zdt); RRD4jItem rrd4jItem = new RRD4jItem(itemName, state, Instant.ofEpochSecond(ts));
items.add(rrd4jItem); items.add(rrd4jItem);
} }
zdt = zdt.plusSeconds(step);
ts += step; ts += step;
} }
return items; return items;