Simplify DateTimeType handling for Amazon DynamoDB

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
This commit is contained in:
Jacob Laursen 2024-11-09 23:02:59 +01:00 committed by lsiepel
parent 6007d6bc51
commit bc540c6653
4 changed files with 22 additions and 29 deletions

View File

@ -292,9 +292,8 @@ public abstract class AbstractDynamoDBItem<T> implements DynamoDBItem<T> {
} else if (item instanceof ContactItem) { } else if (item instanceof ContactItem) {
return new DynamoDBBigDecimalItem(name, convert(state, DecimalType.class).toBigDecimal(), time, expireDays); return new DynamoDBBigDecimalItem(name, convert(state, DecimalType.class).toBigDecimal(), time, expireDays);
} else if (item instanceof DateTimeItem) { } else if (item instanceof DateTimeItem) {
return new DynamoDBStringItem(name, return new DynamoDBStringItem(name, ZONED_DATE_TIME_CONVERTER_STRING
ZONED_DATE_TIME_CONVERTER_STRING.toString(((DateTimeType) state).getZonedDateTime()), time, .toString(((DateTimeType) state).getZonedDateTime(ZoneId.systemDefault())), time, expireDays);
expireDays);
} else if (item instanceof ImageItem) { } else if (item instanceof ImageItem) {
throw new IllegalArgumentException("Unsupported item " + item.getClass().getSimpleName()); throw new IllegalArgumentException("Unsupported item " + item.getClass().getSimpleName());
} else if (item instanceof LocationItem) { } else if (item instanceof LocationItem) {
@ -333,7 +332,8 @@ public abstract class AbstractDynamoDBItem<T> implements DynamoDBItem<T> {
return new DynamoDBStringItem(name, stringType.toString(), time, expireDays); return new DynamoDBStringItem(name, stringType.toString(), time, expireDays);
} else if (state instanceof DateTimeType dateType) { } else if (state instanceof DateTimeType dateType) {
return new DynamoDBStringItem(name, return new DynamoDBStringItem(name,
ZONED_DATE_TIME_CONVERTER_STRING.toString(dateType.getZonedDateTime()), time, expireDays); ZONED_DATE_TIME_CONVERTER_STRING.toString(dateType.getZonedDateTime(ZoneId.systemDefault())),
time, expireDays);
} else { } else {
throw new IllegalStateException( throw new IllegalStateException(
String.format("Unexpected state type %s with StringItem", state.getClass().getSimpleName())); String.format("Unexpected state type %s with StringItem", state.getClass().getSimpleName()));
@ -386,9 +386,7 @@ public abstract class AbstractDynamoDBItem<T> implements DynamoDBItem<T> {
try { try {
// Parse ZoneDateTime from string. DATEFORMATTER assumes UTC in case it is not clear // Parse ZoneDateTime from string. DATEFORMATTER assumes UTC in case it is not clear
// from the string (should be). // from the string (should be).
// We convert to default/local timezone for user convenience (e.g. display) return new DateTimeType(ZONED_DATE_TIME_CONVERTER_STRING.transformTo(stringState));
return new DateTimeType(ZONED_DATE_TIME_CONVERTER_STRING.transformTo(stringState)
.withZoneSameInstant(ZoneId.systemDefault()));
} catch (DateTimeParseException e) { } catch (DateTimeParseException e) {
logger.warn("Failed to parse {} as date. Outputting UNDEF instead", stringState); logger.warn("Failed to parse {} as date. Outputting UNDEF instead", stringState);
return UnDefType.UNDEF; return UnDefType.UNDEF;

View File

@ -20,7 +20,6 @@ import java.time.Instant;
import java.time.ZoneId; import java.time.ZoneId;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.Objects; import java.util.Objects;
import java.util.TimeZone;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
@ -148,10 +147,10 @@ public class AbstractDynamoDBItemSerializationTest {
@CsvSource({ "true", "false" }) @CsvSource({ "true", "false" })
public void testDateTimeTypeWithDateTimeItem(boolean legacy) throws IOException { public void testDateTimeTypeWithDateTimeItem(boolean legacy) throws IOException {
GenericItem item = new DateTimeItem("foo"); GenericItem item = new DateTimeItem("foo");
ZonedDateTime zdt = ZonedDateTime.parse("2016-05-01T13:46:00.050Z"); Instant instant = Instant.parse("2016-05-01T13:46:00.050Z");
DynamoDBItem<?> dbitem = testSerializationToDTO(legacy, item, new DateTimeType(zdt.toString()), DynamoDBItem<?> dbitem = testSerializationToDTO(legacy, item, new DateTimeType(instant),
"2016-05-01T13:46:00.050Z"); "2016-05-01T13:46:00.050Z");
testAsHistoricGeneric(dbitem, item, new DateTimeType(zdt.withZoneSameInstant(ZoneId.systemDefault()))); testAsHistoricGeneric(dbitem, item, new DateTimeType(instant));
} }
@ParameterizedTest @ParameterizedTest
@ -159,7 +158,7 @@ public class AbstractDynamoDBItemSerializationTest {
public void testDateTimeTypeWithStringItem(boolean legacy) throws IOException { public void testDateTimeTypeWithStringItem(boolean legacy) throws IOException {
GenericItem item = new StringItem("foo"); GenericItem item = new StringItem("foo");
DynamoDBItem<?> dbitem = testSerializationToDTO(legacy, item, DynamoDBItem<?> dbitem = testSerializationToDTO(legacy, item,
new DateTimeType(ZonedDateTime.parse("2016-05-01T13:46:00.050Z")), "2016-05-01T13:46:00.050Z"); new DateTimeType(Instant.parse("2016-05-01T13:46:00.050Z")), "2016-05-01T13:46:00.050Z");
testAsHistoricGeneric(dbitem, item, new StringType("2016-05-01T13:46:00.050Z")); testAsHistoricGeneric(dbitem, item, new StringType("2016-05-01T13:46:00.050Z"));
} }
@ -167,10 +166,10 @@ public class AbstractDynamoDBItemSerializationTest {
@CsvSource({ "true", "false" }) @CsvSource({ "true", "false" })
public void testDateTimeTypeLocalWithDateTimeItem(boolean legacy) throws IOException { public void testDateTimeTypeLocalWithDateTimeItem(boolean legacy) throws IOException {
GenericItem item = new DateTimeItem("foo"); GenericItem item = new DateTimeItem("foo");
ZonedDateTime expectedZdt = Instant.ofEpochMilli(1468773487050L).atZone(ZoneId.systemDefault()); Instant expectedInstant = Instant.ofEpochMilli(1468773487050L);
DynamoDBItem<?> dbitem = testSerializationToDTO(legacy, item, new DateTimeType("2016-07-17T19:38:07.050+0300"), DynamoDBItem<?> dbitem = testSerializationToDTO(legacy, item, new DateTimeType("2016-07-17T19:38:07.050+0300"),
"2016-07-17T16:38:07.050Z"); "2016-07-17T16:38:07.050Z");
testAsHistoricGeneric(dbitem, item, new DateTimeType(expectedZdt)); testAsHistoricGeneric(dbitem, item, new DateTimeType(expectedInstant));
} }
@ParameterizedTest @ParameterizedTest
@ -178,8 +177,7 @@ public class AbstractDynamoDBItemSerializationTest {
public void testDateTimeTypeLocalWithStringItem(boolean legacy) throws IOException { public void testDateTimeTypeLocalWithStringItem(boolean legacy) throws IOException {
GenericItem item = new StringItem("foo"); GenericItem item = new StringItem("foo");
Instant instant = Instant.ofEpochMilli(1468773487050L); // GMT: Sun, 17 Jul 2016 16:38:07.050 GMT Instant instant = Instant.ofEpochMilli(1468773487050L); // GMT: Sun, 17 Jul 2016 16:38:07.050 GMT
ZonedDateTime zdt = instant.atZone(TimeZone.getTimeZone("GMT+03:00").toZoneId()); DynamoDBItem<?> dbitem = testSerializationToDTO(legacy, item, new DateTimeType(instant),
DynamoDBItem<?> dbitem = testSerializationToDTO(legacy, item, new DateTimeType(zdt),
"2016-07-17T16:38:07.050Z"); "2016-07-17T16:38:07.050Z");
testAsHistoricGeneric(dbitem, item, new StringType("2016-07-17T16:38:07.050Z")); testAsHistoricGeneric(dbitem, item, new StringType("2016-07-17T16:38:07.050Z"));
} }

View File

@ -225,8 +225,8 @@ public abstract class AbstractTwoItemIntegrationTest extends BaseIntegrationTest
HistoricItem actual1 = iterator.next(); HistoricItem actual1 = iterator.next();
assertFalse(iterator.hasNext()); assertFalse(iterator.hasNext());
assertStateEquals(getFirstItemState(), actual1.getState()); assertStateEquals(getFirstItemState(), actual1.getState());
assertTrue(actual1.getTimestamp().toInstant().isBefore(afterStore1.toInstant())); assertTrue(actual1.getInstant().isBefore(afterStore1.toInstant()));
assertTrue(actual1.getTimestamp().toInstant().isAfter(beforeStore.toInstant())); assertTrue(actual1.getInstant().isAfter(beforeStore.toInstant()));
}); });
} }
@ -246,8 +246,8 @@ public abstract class AbstractTwoItemIntegrationTest extends BaseIntegrationTest
HistoricItem actual1 = iterator.next(); HistoricItem actual1 = iterator.next();
assertFalse(iterator.hasNext()); assertFalse(iterator.hasNext());
assertStateEquals(getFirstItemState(), actual1.getState()); assertStateEquals(getFirstItemState(), actual1.getState());
assertTrue(actual1.getTimestamp().toInstant().isBefore(afterStore1.toInstant())); assertTrue(actual1.getInstant().isBefore(afterStore1.toInstant()));
assertTrue(actual1.getTimestamp().toInstant().isAfter(beforeStore.toInstant())); assertTrue(actual1.getInstant().isAfter(beforeStore.toInstant()));
}); });
} }
@ -267,8 +267,8 @@ public abstract class AbstractTwoItemIntegrationTest extends BaseIntegrationTest
HistoricItem actual1 = iterator.next(); HistoricItem actual1 = iterator.next();
assertFalse(iterator.hasNext()); assertFalse(iterator.hasNext());
assertStateEquals(getFirstItemState(), actual1.getState()); assertStateEquals(getFirstItemState(), actual1.getState());
assertTrue(actual1.getTimestamp().toInstant().isBefore(afterStore1.toInstant())); assertTrue(actual1.getInstant().isBefore(afterStore1.toInstant()));
assertTrue(actual1.getTimestamp().toInstant().isAfter(beforeStore.toInstant())); assertTrue(actual1.getInstant().isAfter(beforeStore.toInstant()));
}); });
} }
@ -304,8 +304,8 @@ public abstract class AbstractTwoItemIntegrationTest extends BaseIntegrationTest
HistoricItem actual1 = iterator.next(); HistoricItem actual1 = iterator.next();
assertFalse(iterator.hasNext()); assertFalse(iterator.hasNext());
assertStateEquals(getFirstItemState(), actual1.getState()); assertStateEquals(getFirstItemState(), actual1.getState());
assertTrue(actual1.getTimestamp().toInstant().isBefore(afterStore1.toInstant())); assertTrue(actual1.getInstant().isBefore(afterStore1.toInstant()));
assertTrue(actual1.getTimestamp().toInstant().isAfter(beforeStore.toInstant())); assertTrue(actual1.getInstant().isAfter(beforeStore.toInstant()));
}); });
} }

View File

@ -12,7 +12,6 @@
*/ */
package org.openhab.persistence.dynamodb.internal; package org.openhab.persistence.dynamodb.internal;
import java.time.ZoneId;
import java.time.ZoneOffset; import java.time.ZoneOffset;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
@ -71,23 +70,21 @@ public class DateTimeItemIntegrationTest extends AbstractTwoItemIntegrationTest
@Override @Override
protected State getFirstItemState() { protected State getFirstItemState() {
// The persistence converts to system default timezone // The persistence converts to system default timezone
// Thus we need to convert here as well for comparison
// In the logs: // In the logs:
// [main] TRACE org.openhab.persistence.dynamodb.internal.DynamoDBPersistenceService - Dynamo item datetime // [main] TRACE org.openhab.persistence.dynamodb.internal.DynamoDBPersistenceService - Dynamo item datetime
// (Type=DateTimeItem, State=2016-06-15T16:00:00.123+0000, Label=null, Category=null) converted to historic // (Type=DateTimeItem, State=2016-06-15T16:00:00.123+0000, Label=null, Category=null) converted to historic
// item: datetime: 2020-11-28T11:29:54.326Z: 2016-06-15T19:00:00.123+0300 // item: datetime: 2020-11-28T11:29:54.326Z: 2016-06-15T19:00:00.123+0300
return STATE1.toZone(ZoneId.systemDefault()); return STATE1;
} }
@Override @Override
protected State getSecondItemState() { protected State getSecondItemState() {
// The persistence converts to system default timezone // The persistence converts to system default timezone
// Thus we need to convert here as well for comparison
// In the logs: // In the logs:
// [main] TRACE org.openhab.persistence.dynamodb.internal.DynamoDBPersistenceService - Dynamo item datetime // [main] TRACE org.openhab.persistence.dynamodb.internal.DynamoDBPersistenceService - Dynamo item datetime
// (Type=DateTimeItem, State=2016-06-15T16:00:00.123+0000, Label=null, Category=null) converted to historic // (Type=DateTimeItem, State=2016-06-15T16:00:00.123+0000, Label=null, Category=null) converted to historic
// item: datetime: 2020-11-28T11:29:54.326Z: 2016-06-15T19:00:00.123+0300 // item: datetime: 2020-11-28T11:29:54.326Z: 2016-06-15T19:00:00.123+0300
return STATE2.toZone(ZoneId.systemDefault()); return STATE2;
} }
@Override @Override