From 12389f083dc236e6547754fda441089262c45791 Mon Sep 17 00:00:00 2001 From: Jacob Laursen Date: Tue, 4 Oct 2022 08:59:59 +0200 Subject: [PATCH] Consolidate and optimize datetime conversions (#13483) Signed-off-by: Jacob Laursen --- .../persistence/jdbc/db/JdbcBaseDAO.java | 37 ++++------- .../persistence/jdbc/db/JdbcDerbyDAO.java | 2 +- .../persistence/jdbc/db/JdbcBaseDAOTest.java | 65 ++++++++++++++++--- 3 files changed, 69 insertions(+), 35 deletions(-) diff --git a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcBaseDAO.java b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcBaseDAO.java index 61d0a12ae..6ba364daf 100644 --- a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcBaseDAO.java +++ b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcBaseDAO.java @@ -348,7 +348,8 @@ public class JdbcBaseDAO { // we already retrieve the unit here once as it is a very costly operation String itemName = item.getName(); Unit> unit = item instanceof NumberItem ? ((NumberItem) item).getUnit() : null; - return m.stream().map(o -> new JdbcHistoricItem(itemName, objectAsState(item, unit, o[1]), objectAsDate(o[0]))) + return m.stream() + .map(o -> new JdbcHistoricItem(itemName, objectAsState(item, unit, o[1]), objectAsZonedDateTime(o[0]))) .collect(Collectors. toList()); } @@ -541,8 +542,7 @@ public class JdbcBaseDAO { } return unit == null ? DecimalType.valueOf(objectAsString(v)) : QuantityType.valueOf(objectAsString(v)); } else if (item instanceof DateTimeItem) { - return new DateTimeType( - ZonedDateTime.ofInstant(Instant.ofEpochMilli(objectAsLong(v)), ZoneId.systemDefault())); + return new DateTimeType(objectAsZonedDateTime(v)); } else if (item instanceof ColorItem) { return HSBType.valueOf(objectAsString(v)); } else if (item instanceof DimmerItem || item instanceof RollershutterItem) { @@ -564,13 +564,17 @@ public class JdbcBaseDAO { } } - protected ZonedDateTime objectAsDate(Object v) { - if (v instanceof LocalDateTime) { - return ZonedDateTime.of((LocalDateTime) v, ZoneId.systemDefault()); - } else if (v instanceof java.sql.Timestamp) { - return ZonedDateTime.ofInstant(((java.sql.Timestamp) v).toInstant(), ZoneId.systemDefault()); + protected ZonedDateTime objectAsZonedDateTime(Object v) { + if (v instanceof Long) { + return ZonedDateTime.ofInstant(Instant.ofEpochMilli(((Number) v).longValue()), ZoneId.systemDefault()); + } else if (v instanceof java.sql.Date) { + return ZonedDateTime.ofInstant(Instant.ofEpochMilli(((java.sql.Date) v).getTime()), ZoneId.systemDefault()); + } else if (v instanceof LocalDateTime) { + return ((LocalDateTime) v).atZone(ZoneId.systemDefault()); } else if (v instanceof Instant) { - return ZonedDateTime.ofInstant((Instant) v, ZoneId.systemDefault()); + return ((Instant) v).atZone(ZoneId.systemDefault()); + } else if (v instanceof java.sql.Timestamp) { + return ((java.sql.Timestamp) v).toInstant().atZone(ZoneId.systemDefault()); } else if (v instanceof java.lang.String) { return ZonedDateTime.ofInstant(java.sql.Timestamp.valueOf(v.toString()).toInstant(), ZoneId.systemDefault()); @@ -578,21 +582,6 @@ public class JdbcBaseDAO { throw new UnsupportedOperationException("Date of type " + v.getClass().getName() + " is not supported"); } - protected Long objectAsLong(Object v) { - if (v instanceof Long) { - return ((Number) v).longValue(); - } else if (v instanceof java.sql.Date) { - return ((java.sql.Date) v).getTime(); - } else if (v instanceof LocalDateTime) { - return ((LocalDateTime) v).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); - } else if (v instanceof Instant) { - return ((Instant) v).toEpochMilli(); - } else if (v instanceof java.sql.Timestamp) { - return ((java.sql.Timestamp) v).getTime(); - } - throw new UnsupportedOperationException("Date of type " + v.getClass().getName() + " is not supported"); - } - protected Integer objectAsInteger(Object v) { if (v instanceof Byte) { return ((Byte) v).intValue(); diff --git a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcDerbyDAO.java b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcDerbyDAO.java index 5c2262f60..431ee56db 100644 --- a/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcDerbyDAO.java +++ b/bundles/org.openhab.persistence.jdbc/src/main/java/org/openhab/persistence/jdbc/db/JdbcDerbyDAO.java @@ -174,7 +174,7 @@ public class JdbcDerbyDAO extends JdbcBaseDAO { Unit> unit = item instanceof NumberItem ? ((NumberItem) item).getUnit() : null; return m.stream().map(o -> { logger.debug("JDBC::doGetHistItemFilterQuery 0='{}' 1='{}'", o[0], o[1]); - return new JdbcHistoricItem(itemName, objectAsState(item, unit, o[1]), objectAsDate(o[0])); + return new JdbcHistoricItem(itemName, objectAsState(item, unit, o[1]), objectAsZonedDateTime(o[0])); }).collect(Collectors. toList()); } diff --git a/bundles/org.openhab.persistence.jdbc/src/test/java/org/openhab/persistence/jdbc/db/JdbcBaseDAOTest.java b/bundles/org.openhab.persistence.jdbc/src/test/java/org/openhab/persistence/jdbc/db/JdbcBaseDAOTest.java index 37146ad07..dfa4d162a 100644 --- a/bundles/org.openhab.persistence.jdbc/src/test/java/org/openhab/persistence/jdbc/db/JdbcBaseDAOTest.java +++ b/bundles/org.openhab.persistence.jdbc/src/test/java/org/openhab/persistence/jdbc/db/JdbcBaseDAOTest.java @@ -17,6 +17,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZonedDateTime; @@ -85,16 +86,6 @@ public class JdbcBaseDAOTest { assertInstanceOf(QuantityType.class, quantityType); assertEquals(QuantityType.valueOf("7.3 °C"), quantityType); - State dateTimeType = jdbcBaseDAO.objectAsState(new DateTimeItem("testDateTimeItem"), null, - java.sql.Timestamp.valueOf("2021-02-01 23:30:02.049")); - assertInstanceOf(DateTimeType.class, dateTimeType); - assertEquals(DateTimeType.valueOf("2021-02-01T23:30:02.049"), dateTimeType); - - dateTimeType = jdbcBaseDAO.objectAsState(new DateTimeItem("testDateTimeItem"), null, - LocalDateTime.parse("2021-02-01T23:30:02.049")); - assertInstanceOf(DateTimeType.class, dateTimeType); - assertEquals(DateTimeType.valueOf("2021-02-01T23:30:02.049"), dateTimeType); - State hsbType = jdbcBaseDAO.objectAsState(new ColorItem("testColorItem"), null, "184,100,52"); assertInstanceOf(HSBType.class, hsbType); assertEquals(HSBType.valueOf("184,100,52"), hsbType); @@ -140,6 +131,60 @@ public class JdbcBaseDAOTest { assertEquals(StringType.valueOf("String"), stringType); } + @Test + public void objectAsStateReturnsValiDateTimeTypeForTimestamp() { + State dateTimeType = jdbcBaseDAO.objectAsState(new DateTimeItem("testDateTimeItem"), null, + java.sql.Timestamp.valueOf("2021-02-01 23:30:02.049")); + assertInstanceOf(DateTimeType.class, dateTimeType); + assertEquals(DateTimeType.valueOf("2021-02-01T23:30:02.049"), dateTimeType); + } + + @Test + public void objectAsStateReturnsValidDateTimeTypeForLocalDateTime() { + State dateTimeType = jdbcBaseDAO.objectAsState(new DateTimeItem("testDateTimeItem"), null, + LocalDateTime.parse("2021-02-01T23:30:02.049")); + assertInstanceOf(DateTimeType.class, dateTimeType); + assertEquals(DateTimeType.valueOf("2021-02-01T23:30:02.049"), dateTimeType); + } + + @Test + public void objectAsStateReturnsValidDateTimeTypeForLong() { + State dateTimeType = jdbcBaseDAO.objectAsState(new DateTimeItem("testDateTimeItem"), null, + Long.valueOf("1612222202049")); + assertInstanceOf(DateTimeType.class, dateTimeType); + assertEquals( + new DateTimeType( + ZonedDateTime.ofInstant(Instant.parse("2021-02-01T23:30:02.049Z"), ZoneId.systemDefault())), + dateTimeType); + } + + @Test + public void objectAsStateReturnsValidDateTimeTypeForSqlDate() { + State dateTimeType = jdbcBaseDAO.objectAsState(new DateTimeItem("testDateTimeItem"), null, + java.sql.Date.valueOf("2021-02-01")); + assertInstanceOf(DateTimeType.class, dateTimeType); + assertEquals(DateTimeType.valueOf("2021-02-01T00:00:00.000"), dateTimeType); + } + + @Test + public void objectAsStateReturnsValidDateTimeTypeForInstant() { + State dateTimeType = jdbcBaseDAO.objectAsState(new DateTimeItem("testDateTimeItem"), null, + Instant.parse("2021-02-01T23:30:02.049Z")); + assertInstanceOf(DateTimeType.class, dateTimeType); + assertEquals( + new DateTimeType( + ZonedDateTime.ofInstant(Instant.parse("2021-02-01T23:30:02.049Z"), ZoneId.systemDefault())), + dateTimeType); + } + + @Test + public void objectAsStateReturnsValidDateTimeTypeForString() { + State dateTimeType = jdbcBaseDAO.objectAsState(new DateTimeItem("testDateTimeItem"), null, + "2021-02-01 23:30:02.049"); + assertInstanceOf(DateTimeType.class, dateTimeType); + assertEquals(DateTimeType.valueOf("2021-02-01T23:30:02.049"), dateTimeType); + } + @Test public void testHistItemFilterQueryProviderReturnsSelectQueryWithoutWhereClauseDescendingOrder() { String sql = jdbcBaseDAO.histItemFilterQueryProvider(filter, 0, DB_TABLE_NAME, "TEST", UTC_ZONE_ID);