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 68e38766eba..ad348263c77 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 @@ -52,6 +52,7 @@ * based on a {@link org.openhab.core.library.types.DateTimeType} stored in an item * * @author Jan N. Klug - Initial contribution + * @author Jimmy Tanagra - Add offset support */ @NonNullByDefault public class DateTimeTriggerHandler extends BaseTriggerModuleHandler @@ -60,6 +61,7 @@ public class DateTimeTriggerHandler extends BaseTriggerModuleHandler public static final String MODULE_TYPE_ID = "timer.DateTimeTrigger"; public static final String CONFIG_ITEM_NAME = "itemName"; public static final String CONFIG_TIME_ONLY = "timeOnly"; + public static final String CONFIG_OFFSET = "offset"; private static final DateTimeFormatter CRON_FORMATTER = DateTimeFormatter.ofPattern("s m H d M * uuuu"); private static final DateTimeFormatter CRON_TIMEONLY_FORMATTER = DateTimeFormatter.ofPattern("s m H * * * *"); @@ -71,6 +73,7 @@ public class DateTimeTriggerHandler extends BaseTriggerModuleHandler private final @Nullable EventFilter eventFilter; private String cronExpression = CronAdjuster.REBOOT; private Boolean timeOnly = false; + private Long offset = 0L; private @Nullable ScheduledCompletableFuture schedule; private @Nullable ServiceRegistration eventSubscriberRegistration; @@ -88,6 +91,7 @@ public DateTimeTriggerHandler(Trigger module, CronScheduler scheduler, ItemRegis this.eventFilter = new TopicPrefixEventFilter("openhab/items/" + itemName + "/"); this.timeOnly = ConfigParser.valueAsOrElse(module.getConfiguration().get(CONFIG_TIME_ONLY), Boolean.class, false); + this.offset = ConfigParser.valueAsOrElse(module.getConfiguration().get(CONFIG_OFFSET), Long.class, 0L); eventSubscriberRegistration = bundleContext.registerService(EventSubscriber.class.getName(), this, null); try { process(itemRegistry.getItem(itemName).getState()); @@ -153,8 +157,8 @@ private synchronized void startScheduler() { cancelScheduler(); if (!CronAdjuster.REBOOT.equals(cronExpression)) { schedule = scheduler.schedule(this, cronExpression); - logger.debug("Scheduled cron job '{}' for trigger '{}'.", module.getConfiguration().get(CONFIG_ITEM_NAME), - module.getId()); + logger.debug("Scheduled cron job '{}' from item '{}' for trigger '{}'.", cronExpression, + module.getConfiguration().get(CONFIG_ITEM_NAME), module.getId()); } } @@ -174,6 +178,7 @@ private void process(Type value) { } else if (value instanceof DateTimeType dateTimeType) { boolean itemIsTimeOnly = dateTimeType.toString().startsWith("1970-01-01T"); cronExpression = dateTimeType.getZonedDateTime().withZoneSameInstant(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/resources/OH-INF/automation/moduletypes/DateTimeTrigger.json b/bundles/org.openhab.core.automation/src/main/resources/OH-INF/automation/moduletypes/DateTimeTrigger.json index 1b08e03aabd..058b43639c6 100644 --- a/bundles/org.openhab.core.automation/src/main/resources/OH-INF/automation/moduletypes/DateTimeTrigger.json +++ b/bundles/org.openhab.core.automation/src/main/resources/OH-INF/automation/moduletypes/DateTimeTrigger.json @@ -29,6 +29,12 @@ "value": "false" } ] + }, + { + "name": "offset", + "type": "INTEGER", + "label": "Offset", + "description": "The offset in seconds to add to the time of the item." } ] } diff --git a/bundles/org.openhab.core.automation/src/main/resources/OH-INF/i18n/automation.properties b/bundles/org.openhab.core.automation/src/main/resources/OH-INF/i18n/automation.properties index 282f321d361..022796a911c 100644 --- a/bundles/org.openhab.core.automation/src/main/resources/OH-INF/i18n/automation.properties +++ b/bundles/org.openhab.core.automation/src/main/resources/OH-INF/i18n/automation.properties @@ -396,6 +396,8 @@ module-type.timer.DateTimeTrigger.config.timeOnly.label = Time only module-type.timer.DateTimeTrigger.config.timeOnly.description = Specifies whether only the time of the item should be compared or the date and time. module-type.timer.DateTimeTrigger.config.timeOnly.option.true = Yes module-type.timer.DateTimeTrigger.config.timeOnly.option.false = No +module-type.timer.DateTimeTrigger.config.offset.label = Offset +module-type.timer.DateTimeTrigger.config.offset.description = The offset in seconds to add to the time of the item. # timer.DayOfWeekCondition diff --git a/bundles/org.openhab.core.automation/src/test/java/org/openhab/core/automation/internal/module/handler/DateTimeTriggerHandlerTest.java b/bundles/org.openhab.core.automation/src/test/java/org/openhab/core/automation/internal/module/handler/DateTimeTriggerHandlerTest.java index c78417708fa..01de9d69320 100644 --- a/bundles/org.openhab.core.automation/src/test/java/org/openhab/core/automation/internal/module/handler/DateTimeTriggerHandlerTest.java +++ b/bundles/org.openhab.core.automation/src/test/java/org/openhab/core/automation/internal/module/handler/DateTimeTriggerHandlerTest.java @@ -80,4 +80,30 @@ public void testDifferentTimeZone() { verify(mockScheduler).schedule(eq(handler), eq("0 0 0 11 8 * 2022")); } + + @Test + public void testOffsetPositive() { + ZonedDateTime zdt = ZonedDateTime.of(2024, 6, 7, 0, 0, 0, 0, ZoneId.systemDefault()); + item.setState(new DateTimeType(zdt)); + when(mockTrigger.getConfiguration()) + .thenReturn(new Configuration(Map.ofEntries(entry(DateTimeTriggerHandler.CONFIG_ITEM_NAME, ITEM_NAME), + entry(DateTimeTriggerHandler.CONFIG_OFFSET, 10)))); + DateTimeTriggerHandler handler = new DateTimeTriggerHandler(mockTrigger, mockScheduler, mockItemRegistry, + mockBundleContext); + + verify(mockScheduler).schedule(eq(handler), eq("10 0 0 7 6 * 2024")); + } + + @Test + public void testOffsetNegative() { + ZonedDateTime zdt = ZonedDateTime.of(2024, 6, 7, 0, 0, 0, 0, ZoneId.systemDefault()); + item.setState(new DateTimeType(zdt)); + when(mockTrigger.getConfiguration()) + .thenReturn(new Configuration(Map.ofEntries(entry(DateTimeTriggerHandler.CONFIG_ITEM_NAME, ITEM_NAME), + entry(DateTimeTriggerHandler.CONFIG_OFFSET, -10)))); + DateTimeTriggerHandler handler = new DateTimeTriggerHandler(mockTrigger, mockScheduler, mockItemRegistry, + mockBundleContext); + + verify(mockScheduler).schedule(eq(handler), eq("50 59 23 6 6 * 2024")); + } }