Skip to content

Commit

Permalink
Remove obsoleted time-zone handling
Browse files Browse the repository at this point in the history
Signed-off-by: Jacob Laursen <[email protected]>
  • Loading branch information
jlaur committed Nov 13, 2024
1 parent e1d2570 commit d691ee3
Show file tree
Hide file tree
Showing 9 changed files with 40 additions and 84 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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) {
Expand All @@ -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;
Expand All @@ -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.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,5 @@
in the reverse
direction.</description>
</parameter>
<parameter name="timezone" type="text">
<label>Time Zone</label>
<description>A time zone to be applied on the state towards the item.</description>
<advanced>true</advanced>
</parameter>
</config-description>
</config-description:config-descriptions>
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<Object[]> 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);
Expand All @@ -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);
Expand All @@ -93,16 +86,15 @@ 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());
}

@ParameterizedTest
@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);
Expand All @@ -113,16 +105,15 @@ 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());
}

@ParameterizedTest
@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);
Expand All @@ -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<String, Object> 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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -40,15 +40,15 @@ 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<State> 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);
}
Expand All @@ -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));
Expand All @@ -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()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<State> 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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit d691ee3

Please sign in to comment.