diff --git a/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/DateTimeTriggerHandler.java b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/DateTimeTriggerHandler.java index 71bc3eb5161..cf1e650984e 100644 --- a/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/DateTimeTriggerHandler.java +++ b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/DateTimeTriggerHandler.java @@ -178,8 +178,7 @@ private void process(Type value) { cronExpression = CronAdjuster.REBOOT; } else if (value instanceof DateTimeType dateTimeType) { boolean itemIsTimeOnly = dateTimeType.toString().startsWith("1970-01-01T"); - cronExpression = dateTimeType.getZonedDateTime().withZoneSameInstant(ZoneId.systemDefault()) - .plusSeconds(offset.longValue()) + cronExpression = dateTimeType.getInstant().atZone(ZoneId.systemDefault()).plusSeconds(offset.longValue()) .format(timeOnly || itemIsTimeOnly ? CRON_TIMEONLY_FORMATTER : CRON_FORMATTER); startScheduler(); } else { diff --git a/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/ItemStateConditionHandler.java b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/ItemStateConditionHandler.java index dbb929a2c1c..21a27849a62 100644 --- a/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/ItemStateConditionHandler.java +++ b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/ItemStateConditionHandler.java @@ -13,6 +13,7 @@ package org.openhab.core.automation.internal.module.handler; import java.time.Duration; +import java.time.Instant; import java.time.LocalDateTime; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; @@ -158,9 +159,9 @@ private boolean lessThanOrEqualsToItemState(String itemName, String state) throw Item item = itemRegistry.getItem(itemName); State compareState = TypeParser.parseState(item.getAcceptedDataTypes(), state); State itemState = item.getState(); - if (itemState instanceof DateTimeType type) { - ZonedDateTime itemTime = type.getZonedDateTime(); - ZonedDateTime compareTime = getCompareTime(state); + if (itemState instanceof DateTimeType dateTimeState) { + Instant itemTime = dateTimeState.getInstant(); + Instant compareTime = getCompareTime(state).toInstant(); return itemTime.compareTo(compareTime) <= 0; } else if (itemState instanceof QuantityType qtState) { if (compareState instanceof DecimalType type) { @@ -195,9 +196,9 @@ private boolean greaterThanOrEqualsToItemState(String itemName, String state) th Item item = itemRegistry.getItem(itemName); State compareState = TypeParser.parseState(item.getAcceptedDataTypes(), state); State itemState = item.getState(); - if (itemState instanceof DateTimeType type) { - ZonedDateTime itemTime = type.getZonedDateTime(); - ZonedDateTime compareTime = getCompareTime(state); + if (itemState instanceof DateTimeType dateTimeState) { + Instant itemTime = dateTimeState.getInstant(); + Instant compareTime = getCompareTime(state).toInstant(); return itemTime.compareTo(compareTime) >= 0; } else if (itemState instanceof QuantityType qtState) { if (compareState instanceof DecimalType type) { diff --git a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/TimestampOffsetProfile.java b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/TimestampOffsetProfile.java index 2534fc6c885..48c43b25968 100644 --- a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/TimestampOffsetProfile.java +++ b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/TimestampOffsetProfile.java @@ -12,14 +12,11 @@ */ package org.openhab.core.thing.internal.profiles; -import java.time.DateTimeException; import java.time.Duration; -import java.time.ZoneId; -import java.time.ZonedDateTime; +import java.time.Instant; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.openhab.core.internal.i18n.I18nProviderImpl; import org.openhab.core.library.types.DateTimeType; import org.openhab.core.thing.profiles.ProfileCallback; import org.openhab.core.thing.profiles.ProfileContext; @@ -36,22 +33,18 @@ /** * Applies the given parameter "offset" to a {@link DateTimeType} state. * - * Options for the "timezone" parameter are provided by the {@link I18nProviderImpl}. - * * @author Christoph Weitkamp - Initial contribution */ @NonNullByDefault public class TimestampOffsetProfile implements StateProfile { static final String OFFSET_PARAM = "offset"; - static final String TIMEZONE_PARAM = "timezone"; private final Logger logger = LoggerFactory.getLogger(TimestampOffsetProfile.class); private final ProfileCallback callback; private final Duration offset; - private @Nullable ZoneId timeZone; public TimestampOffsetProfile(ProfileCallback callback, ProfileContext context) { this.callback = callback; @@ -68,19 +61,6 @@ public TimestampOffsetProfile(ProfileCallback callback, ProfileContext context) OFFSET_PARAM); offset = Duration.ZERO; } - - String timeZoneParam = toStringOrNull(context.getConfiguration().get(TIMEZONE_PARAM)); - logger.debug("Configuring profile with {} parameter '{}'", TIMEZONE_PARAM, timeZoneParam); - if (timeZoneParam == null || timeZoneParam.isBlank()) { - timeZone = null; - } else { - try { - timeZone = ZoneId.of(timeZoneParam); - } catch (DateTimeException e) { - logger.debug("Error setting time zone '{}': {}", timeZoneParam, e.getMessage()); - timeZone = null; - } - } } private @Nullable String toStringOrNull(@Nullable Object value) { @@ -98,20 +78,20 @@ public void onStateUpdateFromItem(State state) { @Override public void onCommandFromItem(Command command) { - callback.handleCommand((Command) applyOffsetAndTimezone(command, false)); + callback.handleCommand((Command) applyOffset(command, false)); } @Override public void onCommandFromHandler(Command command) { - callback.sendCommand((Command) applyOffsetAndTimezone(command, true)); + callback.sendCommand((Command) applyOffset(command, true)); } @Override public void onStateUpdateFromHandler(State state) { - callback.sendUpdate((State) applyOffsetAndTimezone(state, true)); + callback.sendUpdate((State) applyOffset(state, true)); } - private Type applyOffsetAndTimezone(Type type, boolean towardsItem) { + private Type applyOffset(Type type, boolean towardsItem) { if (type instanceof UnDefType) { // we cannot adjust UNDEF or NULL values, thus we simply return them without reporting an error or warning return type; @@ -120,20 +100,15 @@ private Type applyOffsetAndTimezone(Type type, boolean towardsItem) { Duration finalOffset = towardsItem ? offset : offset.negated(); Type result; if (type instanceof DateTimeType timeType) { - ZonedDateTime zdt = timeType.getZonedDateTime(); + Instant instant = timeType.getInstant(); // apply offset if (!Duration.ZERO.equals(offset)) { // we do not need apply an offset equals to 0 - zdt = zdt.plus(finalOffset); + instant = instant.plus(finalOffset); } - // apply time zone - ZoneId localTimeZone = timeZone; - if (localTimeZone != null && !zdt.getZone().equals(localTimeZone) && towardsItem) { - zdt = zdt.withZoneSameInstant(localTimeZone); - } - result = new DateTimeType(zdt); + result = new DateTimeType(instant); } else { logger.warn( "Offset '{}' cannot be applied to the incompatible state '{}' sent from the binding. Returning original state.", diff --git a/bundles/org.openhab.core.thing/src/main/resources/OH-INF/config/timestampOffsetProfile.xml b/bundles/org.openhab.core.thing/src/main/resources/OH-INF/config/timestampOffsetProfile.xml index 9206970cec1..92ebd73035d 100644 --- a/bundles/org.openhab.core.thing/src/main/resources/OH-INF/config/timestampOffsetProfile.xml +++ b/bundles/org.openhab.core.thing/src/main/resources/OH-INF/config/timestampOffsetProfile.xml @@ -12,10 +12,5 @@ in the reverse direction. - - - A time zone to be applied on the state towards the item. - true - diff --git a/bundles/org.openhab.core.thing/src/main/resources/OH-INF/i18n/SystemProfiles.properties b/bundles/org.openhab.core.thing/src/main/resources/OH-INF/i18n/SystemProfiles.properties index e4837fd5e9f..8b2c08f356c 100644 --- a/bundles/org.openhab.core.thing/src/main/resources/OH-INF/i18n/SystemProfiles.properties +++ b/bundles/org.openhab.core.thing/src/main/resources/OH-INF/i18n/SystemProfiles.properties @@ -21,7 +21,5 @@ profile-type.system.timestamp-change.label = Timestamp on Change profile-type.system.timestamp-offset.label = Timestamp Offset profile.config.system.timestamp-offset.offset.label = Offset profile.config.system.timestamp-offset.offset.description = Offset to be applied on the state towards the item. The negative offset will be applied in the reverse direction. -profile.config.system.timestamp-offset.timezone.label = Time Zone -profile.config.system.timestamp-offset.timezone.description = A time zone to be applied on the state. profile-type.system.timestamp-trigger.label = Timestamp on Trigger profile-type.system.timestamp-update.label = Timestamp on Update diff --git a/bundles/org.openhab.core.thing/src/test/java/org/openhab/core/thing/internal/profiles/TimestampOffsetProfileTest.java b/bundles/org.openhab.core.thing/src/test/java/org/openhab/core/thing/internal/profiles/TimestampOffsetProfileTest.java index 3a0e4e19ef4..431d7e7f77a 100644 --- a/bundles/org.openhab.core.thing/src/test/java/org/openhab/core/thing/internal/profiles/TimestampOffsetProfileTest.java +++ b/bundles/org.openhab.core.thing/src/test/java/org/openhab/core/thing/internal/profiles/TimestampOffsetProfileTest.java @@ -21,7 +21,6 @@ import java.util.Map; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -44,28 +43,23 @@ public class TimestampOffsetProfileTest { public static class ParameterSet { public final long seconds; - public final @Nullable String timeZone; - public ParameterSet(long seconds, @Nullable String timeZone) { + public ParameterSet(long seconds) { this.seconds = seconds; - this.timeZone = timeZone; } } public static Collection parameters() { return List.of(new Object[][] { // - { new ParameterSet(0, null) }, // - { new ParameterSet(30, null) }, // - { new ParameterSet(-30, null) }, // - { new ParameterSet(0, "Europe/Berlin") }, // - { new ParameterSet(30, "Europe/Berlin") }, // - { new ParameterSet(-30, "Europe/Berlin") } }); + { new ParameterSet(0) }, // + { new ParameterSet(30) }, // + { new ParameterSet(-30) } }); } @Test public void testUNDEFOnStateUpdateFromHandler() { ProfileCallback callback = mock(ProfileCallback.class); - TimestampOffsetProfile offsetProfile = createProfile(callback, Long.toString(60), null); + TimestampOffsetProfile offsetProfile = createProfile(callback, Long.toString(60)); State state = UnDefType.UNDEF; offsetProfile.onStateUpdateFromHandler(state); @@ -81,8 +75,7 @@ public void testUNDEFOnStateUpdateFromHandler() { @MethodSource("parameters") public void testOnCommandFromItem(ParameterSet parameterSet) { ProfileCallback callback = mock(ProfileCallback.class); - TimestampOffsetProfile offsetProfile = createProfile(callback, Long.toString(parameterSet.seconds), - parameterSet.timeZone); + TimestampOffsetProfile offsetProfile = createProfile(callback, Long.toString(parameterSet.seconds)); Command cmd = DateTimeType.valueOf("2021-03-30T10:58:47.033+0000"); offsetProfile.onCommandFromItem(cmd); @@ -93,7 +86,7 @@ public void testOnCommandFromItem(ParameterSet parameterSet) { Command result = capture.getValue(); DateTimeType updateResult = (DateTimeType) result; DateTimeType expectedResult = new DateTimeType( - ((DateTimeType) cmd).getZonedDateTime().minusSeconds(parameterSet.seconds)); + ((DateTimeType) cmd).getInstant().minusSeconds(parameterSet.seconds)); assertEquals(expectedResult.getInstant(), updateResult.getInstant()); } @@ -101,8 +94,7 @@ public void testOnCommandFromItem(ParameterSet parameterSet) { @MethodSource("parameters") public void testOnCommandFromHandler(ParameterSet parameterSet) { ProfileCallback callback = mock(ProfileCallback.class); - TimestampOffsetProfile offsetProfile = createProfile(callback, Long.toString(parameterSet.seconds), - parameterSet.timeZone); + TimestampOffsetProfile offsetProfile = createProfile(callback, Long.toString(parameterSet.seconds)); Command cmd = new DateTimeType("2021-03-30T10:58:47.033+0000"); offsetProfile.onCommandFromHandler(cmd); @@ -113,7 +105,7 @@ public void testOnCommandFromHandler(ParameterSet parameterSet) { Command result = capture.getValue(); DateTimeType updateResult = (DateTimeType) result; DateTimeType expectedResult = new DateTimeType( - ((DateTimeType) cmd).getZonedDateTime().plusSeconds(parameterSet.seconds)); + ((DateTimeType) cmd).getInstant().plusSeconds(parameterSet.seconds)); assertEquals(expectedResult.getInstant(), updateResult.getInstant()); } @@ -121,8 +113,7 @@ public void testOnCommandFromHandler(ParameterSet parameterSet) { @MethodSource("parameters") public void testOnStateUpdateFromHandler(ParameterSet parameterSet) { ProfileCallback callback = mock(ProfileCallback.class); - TimestampOffsetProfile offsetProfile = createProfile(callback, Long.toString(parameterSet.seconds), - parameterSet.timeZone); + TimestampOffsetProfile offsetProfile = createProfile(callback, Long.toString(parameterSet.seconds)); State state = new DateTimeType("2021-03-30T10:58:47.033+0000"); offsetProfile.onStateUpdateFromHandler(state); @@ -133,17 +124,14 @@ public void testOnStateUpdateFromHandler(ParameterSet parameterSet) { State result = capture.getValue(); DateTimeType updateResult = (DateTimeType) result; DateTimeType expectedResult = new DateTimeType( - ((DateTimeType) state).getZonedDateTime().plusSeconds(parameterSet.seconds)); + ((DateTimeType) state).getInstant().plusSeconds(parameterSet.seconds)); assertEquals(expectedResult.getInstant(), updateResult.getInstant()); } - private TimestampOffsetProfile createProfile(ProfileCallback callback, String offset, @Nullable String timeZone) { + private TimestampOffsetProfile createProfile(ProfileCallback callback, String offset) { ProfileContext context = mock(ProfileContext.class); Map properties = new HashMap<>(); properties.put(TimestampOffsetProfile.OFFSET_PARAM, offset); - if (timeZone != null) { - properties.put(TimestampOffsetProfile.TIMEZONE_PARAM, timeZone); - } when(context.getConfiguration()).thenReturn(new Configuration(properties)); return new TimestampOffsetProfile(callback, context); } diff --git a/bundles/org.openhab.core.thing/src/test/java/org/openhab/core/thing/internal/profiles/TimestampProfileTest.java b/bundles/org.openhab.core.thing/src/test/java/org/openhab/core/thing/internal/profiles/TimestampProfileTest.java index 988d7d1cdb7..3bf76b3edce 100644 --- a/bundles/org.openhab.core.thing/src/test/java/org/openhab/core/thing/internal/profiles/TimestampProfileTest.java +++ b/bundles/org.openhab.core.thing/src/test/java/org/openhab/core/thing/internal/profiles/TimestampProfileTest.java @@ -15,7 +15,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.*; -import java.time.ZonedDateTime; +import java.time.Instant; import java.time.temporal.ChronoUnit; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -40,7 +40,7 @@ public void testTimestampOnUpdateStateUpdateFromHandler() { ProfileCallback callback = mock(ProfileCallback.class); TimestampUpdateProfile timestampProfile = new TimestampUpdateProfile(callback); - ZonedDateTime now = ZonedDateTime.now(); + Instant now = Instant.now(); timestampProfile.onStateUpdateFromHandler(new DecimalType(23)); ArgumentCaptor capture = ArgumentCaptor.forClass(State.class); @@ -48,7 +48,7 @@ public void testTimestampOnUpdateStateUpdateFromHandler() { State result = capture.getValue(); DateTimeType updateResult = (DateTimeType) result; - ZonedDateTime timestamp = updateResult.getZonedDateTime(); + Instant timestamp = updateResult.getInstant(); long difference = ChronoUnit.MINUTES.between(now, timestamp); assertTrue(difference < 1); } @@ -66,7 +66,7 @@ public void testTimestampOnChangeStateUpdateFromHandler() { State result = capture.getValue(); DateTimeType changeResult = (DateTimeType) result; - waitForAssert(() -> assertTrue(ZonedDateTime.now().isAfter(changeResult.getZonedDateTime()))); + waitForAssert(() -> assertTrue(Instant.now().isAfter(changeResult.getInstant()))); // The state is unchanged, no additional call to the callback timestampProfile.onStateUpdateFromHandler(new DecimalType(23)); @@ -77,6 +77,6 @@ public void testTimestampOnChangeStateUpdateFromHandler() { verify(callback, times(2)).sendUpdate(capture.capture()); result = capture.getValue(); DateTimeType updatedResult = (DateTimeType) result; - assertTrue(updatedResult.getZonedDateTime().isAfter(changeResult.getZonedDateTime())); + assertTrue(updatedResult.getInstant().isAfter(changeResult.getInstant())); } } diff --git a/bundles/org.openhab.core.thing/src/test/java/org/openhab/core/thing/internal/profiles/TimestampTriggerProfileTest.java b/bundles/org.openhab.core.thing/src/test/java/org/openhab/core/thing/internal/profiles/TimestampTriggerProfileTest.java index 3275c57f808..7bb9a05d04f 100644 --- a/bundles/org.openhab.core.thing/src/test/java/org/openhab/core/thing/internal/profiles/TimestampTriggerProfileTest.java +++ b/bundles/org.openhab.core.thing/src/test/java/org/openhab/core/thing/internal/profiles/TimestampTriggerProfileTest.java @@ -15,7 +15,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.*; -import java.time.ZonedDateTime; +import java.time.Instant; import java.time.temporal.ChronoUnit; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -38,14 +38,14 @@ public void testTimestampOnTrigger() { ProfileCallback callback = mock(ProfileCallback.class); TriggerProfile profile = new TimestampTriggerProfile(callback); - ZonedDateTime now = ZonedDateTime.now(); + Instant now = Instant.now(); profile.onTriggerFromHandler(CommonTriggerEvents.PRESSED); ArgumentCaptor capture = ArgumentCaptor.forClass(State.class); verify(callback, times(1)).sendUpdate(capture.capture()); State result = capture.getValue(); DateTimeType updateResult = (DateTimeType) result; - ZonedDateTime timestamp = updateResult.getZonedDateTime(); + Instant timestamp = updateResult.getInstant(); long difference = ChronoUnit.MINUTES.between(now, timestamp); assertTrue(difference < 1); } diff --git a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java index 5884192abfa..86d5b7261b3 100644 --- a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java +++ b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/items/ItemUIRegistryImpl.java @@ -12,7 +12,7 @@ */ package org.openhab.core.ui.internal.items; -import java.time.ZonedDateTime; +import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Collection; @@ -1145,9 +1145,9 @@ private boolean matchStateToValue(State state, String value, @Nullable String ma } catch (NumberFormatException e) { logger.debug("matchStateToValue: Decimal format exception: ", e); } - } else if (state instanceof DateTimeType type) { - ZonedDateTime val = type.getZonedDateTime(); - ZonedDateTime now = ZonedDateTime.now(); + } else if (state instanceof DateTimeType dateTimeState) { + Instant val = dateTimeState.getInstant(); + Instant now = Instant.now(); long secsDif = ChronoUnit.SECONDS.between(val, now); try {